-
1
class AdminController < ApplicationController
-
1
def new_instructor
-
1
@user = User.find_or_create_by_name(params[:name])
-
-
# these values need to be true by default so new users receive e-mail on these events unless they opt not to
-
1
if @user.new_record?
-
1
@user.email_on_review = true
-
1
@user.email_on_submission = true
-
1
@user.email_on_review_of_review = true
-
1
@user.role = Role.instructor
-
end
-
end
-
-
1
def create_instructor
-
1
if params['save']
-
@user = User.find_or_create_by_name params[:user][:name]
-
@user.role = Role.instructor
-
@user.update_attributes(params[:user])
-
redirect_to :action => 'list_instructors'
-
else
-
1
@user = User.new(params[:user])
-
1
@user.parent_id = (session[:user]).id
-
1
@user.role_id = Role.instructor.id
-
-
1
if @user.save
-
flash[:notice] = 'Instructor was successfully created.'
-
redirect_to :action => 'list_instructors'
-
else
-
render :action => 'new_instructor'
-
end
-
end
-
end
-
-
1
def list_instructors
-
1
@users = User.
-
instructors.
-
order(:name).
-
where("parent_id = ?", current_user.id).
-
paginate(:page => params[:page], :per_page => 50)
-
end
-
-
1
def add_administrator
-
@user = User.new
-
end
-
-
1
def new_administrator
-
add_administrator
-
end
-
-
1
def save_administrator # saves newly created administrator to database
-
PgUsersController.create(Role.administrator.id, :admin_controller, :list_administrators, :add_administrator)
-
end
-
-
1
def create_administrator
-
save_administrator
-
end
-
-
1
def list_administrators
-
@users = User.
-
admins.
-
order(:name).
-
where("parent_id = ?", current_user.id).
-
paginate(:page => params[:page], :per_page => 50)
-
end
-
-
1
def list_users(conditions)
-
@users = User.paginate(:page => params[:page], :order => 'name',:conditions => conditions, :per_page => 50)
-
end
-
-
1
def new_super_administrator
-
@user = User.new
-
end
-
-
1
def list_super_administrators
-
@users = User.find(:all, :conditions => ["role_id = ?", Role.superadministrator.id])
-
end
-
-
1
def show_instructor
-
@user = User.find(params[:id])
-
if @user.role_id
-
@role = Role.find(@user.role_id)
-
else
-
@role = Role.new(:id => nil, :name => '(none)')
-
end
-
end
-
-
1
def remove_instructor
-
User.find(params[:id]).destroy
-
redirect_to :action => 'list_instructors'
-
end
-
-
1
def save_super_administrator
-
PgUsersController.create(Role.superadministrator.id, :admin_controller, :list_super_administrators, :new_super_administrator)
-
end
-
end
-
1
class AdvertiseForPartnerController < ApplicationController
-
-
#adds a new advertise for partners entry in team table...
-
1
def new
-
puts "team #{params[:team_id]}"
-
end
-
-
#removes an entry from team table for corresponding team who requested to remove their advertisement for partner request
-
1
def remove
-
team = Team.find(params[:team_id])
-
team.advertise_for_partner = false
-
team.comments_for_advertisement = nil
-
team.save
-
-
assignment=Assignment.find(Team.find(params[:team_id]).parent_id)
-
participant=Participant.find_by_parent_id_and_user_id(assignment.id,session[:user].id)
-
redirect_to :controller => 'student_team', :action => 'view' , :id => participant.id
-
end
-
-
#update the team table with newly created advertise for partner request for the corresponding team
-
1
def create
-
team = Team.find(params[:id])
-
team.advertise_for_partner = true
-
team.comments_for_advertisement = params[:comments_for_advertisement]
-
team.save
-
-
assignment=Assignment.find(Team.find(params[:id]).parent_id)
-
participant=Participant.find_by_parent_id_and_user_id(assignment.id,session[:user].id)
-
redirect_to :controller => 'student_team', :action => 'view' , :id => participant.id
-
end
-
-
#update the advertisement when done with editing #####This should be edit rather than update....
-
1
def update
-
@team=Team.find(params[:id])
-
#@team.comments_for_advertisement = params[:comments_for_advertisement]
-
Team.update(params[:id], :comments_for_advertisement => params[:comments_for_advertisement])
-
assignment=Assignment.find(Team.find(params[:id]).parent_id)
-
participant=Participant.find_by_parent_id_and_user_id(assignment.id,session[:user].id)
-
if @team.save
-
flash[:notice]='Advertisement updated successfully!'
-
redirect_to :controller => 'student_team', :action => 'view' , :id => participant.id
-
else
-
flash[:error]='Advertisement not updated!'
-
redirect_to :controller => 'student_team', :action => 'view' , :id => participant.id
-
end
-
end
-
-
#find the team who wants to edit their advertisement
-
1
def edit
-
@team = Team.find(params[:team_id])
-
end
-
end
-
1
class AdviceController < ApplicationController
-
-
# Modify the advice associated with a questionnaire
-
1
def edit_advice
-
@questionnaire = get(Questionnaire, params[:id])
-
-
for question in @questionnaire.questions
-
if question.true_false
-
num_questions = 2
-
else
-
num_questions = @questionnaire.max_question_score - @questionnaire.min_question_score
-
end
-
-
sorted_advice = question.question_advices.sort_by { |x| -x.score }
-
if question.question_advices.length != num_questions or
-
sorted_advice[0].score != @questionnaire.min_question_score or
-
sorted_advice[sorted_advice.length-1] != @questionnaire.max_question_score
-
# The number of advices for this question has changed.
-
QuestionnaireHelper::adjust_advice_size(@questionnaire, question)
-
end
-
end
-
end
-
-
# save the advice for a questionnaire
-
1
def save_advice
-
@questionnaire = get(Questionnaire, params[:id])
-
-
begin
-
for advice_key in params[:advice].keys
-
QuestionAdvice.update(advice_key, params[:advice][advice_key])
-
end
-
flash[:notice] = "The questionnaire's question advice was successfully saved"
-
redirect_to :action => 'edit_advice', :id => params[:id]
-
-
rescue ActiveRecord::RecordNotFound
-
render :action => 'edit_advice', :id => params[:id]
-
end
-
end
-
end
-
1
class AnalyticController < ApplicationController
-
1
include CourseHelper
-
1
include AnalyticHelper
-
-
1
before_filter :init
-
1
def index
-
-
end
-
1
def init
-
#all internal not use by the page
-
@available_scope_types = [:courses, :assignments, :teams]
-
@available_graph_types = [:line, :bar, :pie, :scatter]
-
@available_courses = associated_courses(session[:user])
-
-
#Hash of available method name of the data mining methods with different type of selection
-
@available_data_types = Hash.new
-
#data type by scope
-
@available_data_types[:course] = CourseAnalytic.instance_methods
-
@available_data_types[:assignment] = AssignmentAnalytic.instance_methods
-
@available_data_types[:team] = AssignmentTeamAnalytic.instance_methods
-
#data type by chart type
-
@available_data_types[:bar] = [
-
#general
-
"num_participants",
-
"num_assignments",
-
"num_teams",
-
"num_participants",
-
"num_reviews",
-
#assignment_teams
-
"total_num_assignment_teams",
-
"average_num_assignment_teams",
-
"max_num_assignment_teams",
-
"min_num_assignment_teams",
-
#assignment_scores
-
"average_assignment_score",
-
"max_assignment_score",
-
"min_assignment_score",
-
#assignment_reviews
-
"total_num_assignment_reviews",
-
"average_num_assignment_reviews",
-
"max_num_assignment_reviews",
-
"min_num_assignment_reviews",
-
#team_reviews
-
"total_num_team_reviews",
-
"average_num_team_reviews",
-
"max_num_team_reviews",
-
"min_num_team_reviews",
-
#team_scores
-
"average_team_score",
-
"max_team_score",
-
"min_team_score",
-
#review_score
-
"average_review_score",
-
"max_review_score",
-
"min_review_score",
-
#review_word_count
-
"total_review_word_count",
-
"average_review_word_count",
-
"max_review_word_count",
-
"min_review_word_count",
-
#character_count
-
"total_review_character_count",
-
"average_review_character_count",
-
"max_review_character_count",
-
"min_review_character_count"
-
]
-
-
@available_data_types[:scatter] = [
-
-
]
-
@available_data_types[:line] = []
-
@available_data_types[:pie] = []
-
end
-
-
1
def graph_data_type_list
-
#cross checking @available_data_type[chart_type] with @available_data_type[scope]
-
data_type_list = @available_data_types[params[:scope].to_sym] & @available_data_types[params[:type].to_sym]
-
data_type_list.sort!
-
respond_to do |format|
-
format.json { render :json => data_type_list}
-
end
-
end
-
-
#dataPoint = [
-
# {:name => 'review 1', :data => [9.9, 7.5, 6.4, 9.2, 4.0, 6.0, 5.6, 8.5, 6.4, 4.1, 5.6, 4.4]},
-
# {:name => 'review 2', :data => [3.6, 8.8, 8.5, 3.4, 6.0, 4.5, 5.0, 4.3, 9.2, 8.5, 6.6, 9.3]},
-
# {:name => 'review 3', :data => [8.9, 8.8, 9.3, 4.4, 7.0, 8.3, 9.0, 9.6, 5.4, 6.2, 9.3, 5.2]}
-
#]
-
#options2 = {
-
# :title => "this is title2",
-
# :x_axis_categories => [ 'Problem1', 'Problem2', 'Problem3', 'Problem4', 'Problem5', 'Problem6', 'Problem7', 'Problem8', 'Problem9', 'Problem10', 'Problem11','Problem12']
-
#}
-
#Chart.new(:bar, dataPoint, options2)
-
#should be rename to graph_data_packet
-
1
def get_graph_data_bundle
-
if params[:id].nil? or params[:data_type].nil?
-
respond_to do |format|
-
format.json { render :json => nil }
-
end
-
return
-
end
-
-
case params[:type]
-
when "line"
-
chart_data = line_graph_data(params[:scope], params[:id], params[:data_type])
-
when "bar"
-
chart_data = bar_chart_data(params[:scope], params[:id], params[:data_type])
-
when "scatter"
-
chart_data = scatter_plot_data(params[:scope], params[:id], params[:data_type])
-
when "pie"
-
chart_data = pie_chart_data(params[:scope], params[:id], params[:data_type])
-
end
-
-
respond_to do |format|
-
format.json { render :json => chart_data }
-
end
-
end
-
-
-
-
1
def course_list
-
courses = associated_courses(session[:user])
-
course_list = Array.new
-
courses.each do |course|
-
course_list << [course.name, course.id]
-
end
-
respond_to do |format|
-
format.json { render :json => sort_by_name(course_list) }
-
end
-
end
-
-
1
def assignment_list
-
course = Course.find(params[:course_id])
-
assignments = course.assignments
-
assignment_list = Array.new
-
assignments.each do |assignment|
-
assignment_list << [assignment.name, assignment.id]
-
end
-
respond_to do |format|
-
format.json { render :json => sort_by_name(assignment_list) }
-
end
-
end
-
-
1
def team_list
-
assignment = Assignment.find(params[:assignment_id])
-
teams = assignment.teams
-
team_list = Array.new
-
teams.each do |team|
-
team_list << [team.name, team.id]
-
end
-
respond_to do |format|
-
format.json { render :json => sort_by_name(team_list) }
-
end
-
end
-
-
1
def render_sample
-
-
end
-
-
-
end
-
1
require 'goldberg_filters'
-
-
1
class ApplicationController < ActionController::Base
-
1
include GoldbergFilters
-
-
1
helper_method :current_user_session, :current_user, :current_user_role?
-
1
protect_from_forgery unless Rails.env.test?
-
1
filter_parameter_logging :password, :password_confirmation, :clear_password, :clear_password_confirmation
-
1
before_filter :set_time_zone
-
#before_filter :goldberg_security_filter
-
-
1
def authorize(args = {})
-
#unless current_permission(args).allow?(params[:controller], params[:action])
-
#flash[:warn] = 'Please log in.'
-
#redirect_back
-
#end
-
3
@user = current_user
-
end
-
-
1
def current_permission(args = {})
-
@authority ||= Authority.new args.merge({
-
current_user: current_user
-
})
-
end
-
1
delegate :allow?, to: :current_permission
-
1
helper_method :allow?
-
-
1
def current_user_role?
-
current_user.role.name
-
end
-
1
helper_method :current_user_role?
-
-
1
def current_user
-
225
@current_user ||= session[:user]
-
end
-
1
helper_method :current_user
-
-
1
def current_user_role
-
current_user.role
-
end
-
1
alias_method :current_user_role?, :current_user_role
-
-
1
def logged_in?
-
current_user
-
end
-
-
1
def redirect_back(default = :root)
-
redirect_to request.env['HTTP_REFERER'] ? :back : default
-
end
-
-
1
def set_time_zone
-
83
Time.zone = current_user.timezonepref if current_user
-
end
-
-
1
private
-
-
1
def require_user
-
invalid_login_status('in') unless current_user
-
end
-
-
1
def require_no_user
-
invalid_login_status('out') if current_user
-
end
-
-
1
def invalid_login_status(status)
-
flash[:notice] = "You must be logged #{status} to access this page"
-
redirect_back
-
end
-
-
1
protected
-
-
1
def set_up_display_options(object_type)
-
# Create a set that will be used to populate the dropbox when a user lists a set of objects (assgts., questionnaires, etc.)
-
# Get the Instructor::QUESTIONNAIRE constant
-
@display_options ||= eval "#{current_user_role.class}::#{object_type}"
-
end
-
-
# Use this method to validate the current user in order to avoid allowing users
-
# to see unauthorized data.
-
# Ex: return unless current_user_id?(params[:user_id])
-
1
def current_user_id?(user_id)
-
current_user.try(:id) == user_id
-
end
-
-
1
def denied(reason=nil)
-
if reason
-
redirect_to "/denied?reason=#{reason}"
-
else
-
redirect_to "/denied"
-
end
-
end
-
end
-
1
class Assessment360Controller < ApplicationController
-
# Added the @instructor to display the instrucor name in the home page of the 360 degree assessment
-
1
def index
-
@courses = Course.find_all_by_instructor_id(session[:user].id)
-
@instructor_id = session[:user].id
-
@instructor = User.find_by_id(@instructor_id)
-
end
-
-
1
def one_course_all_assignments
-
puts "inside one course all assignment"
-
#@REVIEW_TYPES = ["ParticipantReviewResponseMap", "FeedbackResponseMap", "TeammateReviewResponseMap", "MetareviewResponseMap"]
-
@REVIEW_TYPES = ["TeammateReviewResponseMap"]
-
@course = Course.find_by_id(params[:course_id])
-
@assignments = Assignment.find_all_by_course_id(@course)
-
@assignments.reject! {|assignment| assignment.get_total_reviews_assigned_by_type(@REVIEW_TYPES.first) == 0 }
-
-
@assignment_pie_charts = Hash.new
-
@assignment_bar_charts = Hash.new
-
@assignment_distribution = Hash.new
-
-
@assignments.each do |assignment|
-
# Pie Chart Data .....................................
-
reviewed = Response.get_percentage_reviews_completed(assignment.id)
-
pending = 100 - reviewed
-
reviewed_msg = reviewed.to_s + "% reviewed"
-
pending_msg = pending.to_s + "% pending"
-
-
GoogleChart::PieChart.new('160x100'," ",false) do |pc|
-
pc.data_encoding = :extended
-
pc.data reviewed_msg, reviewed, '228b22' # want to write '20' responed
-
pc.data pending_msg, pending, 'ff0000' # rest of the class
-
-
# Pie Chart with labels
-
pc.show_labels = false
-
pc.show_legend = true
-
@assignment_pie_charts[assignment] = (pc.to_url)
-
end
-
-
# bar chart data ................................
-
bar_1_data = Array.new
-
dates = Array.new
-
date = assignment.created_at.to_datetime.to_date
-
-
while ((date <=> Date.today) <= 0)
-
if Response.get_total_reviews_completed_by_type_and_date(assignment.id, @REVIEW_TYPES.first, date) != 0 then
-
bar_1_data.push(Response.get_total_reviews_completed_by_type_and_date(assignment.id, @REVIEW_TYPES.first, date))
-
dates.push(date.month.to_s + "-" + date.day.to_s)
-
end
-
-
date = (date.to_datetime.advance(:days => 1)).to_date
-
end
-
-
color_1 = 'c53711'
-
min=0
-
#max= assignment.get_total_reviews_assigned
-
max = Response.get_total_reviews_assigned(assignment.id)
-
-
GoogleChart::BarChart.new("600x80", " ", :vertical, false) do |bc|
-
bc.data "Review", bar_1_data, color_1
-
bc.axis :y, :positions => [min, max], :range => [min,max]
-
bc.axis :x, :labels => dates
-
bc.show_legend = false
-
bc.stacked = false
-
bc.data_encoding = :extended
-
bc.params.merge!({:chl => "Nov"})
-
@assignment_bar_charts[assignment] = (bc.to_url)
-
end
-
-
# Histogram score distribution .......................
-
bar_2_data = Response.get_score_distribution(assignment.id)
-
color_2 = '4D89F9'
-
min = 0
-
max = 100
-
-
p '======================='
-
p bar_2_data
-
GoogleChart::BarChart.new("130x100", " ", :vertical, false) do |bc|
-
bc.data "Review", bar_2_data, color_2
-
bc.axis :y, :positions => [0, bar_2_data.max], :range => [0, bar_2_data.max]
-
bc.axis :x, :positions => [min, max], :range => [min,max]
-
bc.width_spacing_options :bar_width => 1, :bar_spacing => 0, :group_spacing => 0
-
bc.show_legend = false
-
bc.stacked = false
-
bc.data_encoding = :extended
-
bc.params.merge!({:chl => "Nov"})
-
@assignment_distribution[assignment] = (bc.to_url)
-
end
-
end
-
end
-
-
1
def all_assignments_all_students
-
@course = Course.find_by_id(params[:course_id]);
-
@assignments = Assignment.find_all_by_course_id(@course)
-
end
-
-
1
def one_assignment_all_students
-
@assignment = Assignment.find_by_id(params[:assignment_id])
-
@participants = @assignment.participants
-
-
@bc = Hash.new
-
@participants.each do |participant|
-
@questionnaires = @assignment.questionnaires
-
bar_1_data = [participant.get_average_score]
-
color_1 = 'c53711'
-
min = 0
-
max = 100
-
-
GoogleChart::BarChart.new("300x40", " ", :horizontal, false) do |bc|
-
bc.data " ", [100], 'ffffff'
-
bc.data "Student", bar_1_data, color_1
-
bc.axis :x, :range => [min,max]
-
bc.show_legend = false
-
bc.stacked = false
-
bc.data_encoding = :extended
-
@bc[participant.user.id] = bc.to_url
-
end
-
end
-
end
-
-
# Find the list of all students and assignments pertaining to the course. This data is used to compute the metareview and teammate review scores. This information is used in the view.
-
1
def all_students_all_reviews
-
@course = Course.find_by_id(params[:course_id])
-
@students = @course.get_participants()
-
@assignments = Assignment.find_all_by_course_id(@course.id);
-
end
-
-
# Find all the assignments for a given student pertaining to the course. This data is given a graphical display using bar charts. Individual teammate and metareview scores are displayed along with their aggregate
-
1
def one_student_all_reviews
-
-
@course = Course.find_by_id(params[:course_id])
-
@students = @course.get_participants()
-
@students.each { |student|
-
if student.id.to_s == params[:student_id].to_s
-
@current_student = student
-
break
-
end
-
}
-
@assignments = Assignment.find_all_by_course_id(@course.id);
-
-
colors = Array.new
-
colors << '0000ff'
-
colors << '00ff00'
-
colors << 'ff0000'
-
colors << 'ff00ff'
-
colors << '00ffff'
-
colors << 'ffff00'
-
colors << '0f0f0f'
-
colors << 'f0f0f0'
-
colors << 'f00f00'
-
colors << 'f0f00f'
-
colors << 'ff000f'
-
min = 0
-
max = 100
-
GoogleChart::BarChart.new("600x350"," ",:horizontal,false) do |bc|
-
bc.data " ", [100], 'ffffff'
-
bc.axis :x, :range => [min,max]
-
i = 0
-
@assignments.each do |assignment|
-
assignment_participant = assignment.participants.find_by_user_id(@current_student.user_id)
-
if !assignment_participant.nil?
-
teammate_scores = assignment_participant.get_teammate_reviews()
-
meta_scores = assignment_participant.get_metareviews()
-
j = 1.to_i
-
average = 0;
-
if !teammate_scores.nil?
-
teammate_scores.each do |teammate_score|
-
average = average + teammate_score.get_average_score
-
bc.data assignment.name.to_s + ", Scores: " + teammate_score.get_average_score.to_s, [teammate_score.get_average_score], colors[i]
-
j = j + 1
-
end
-
if( (j-1).to_i > 0)
-
average = average.to_i / (j-1).to_i
-
bc.data assignment.name.to_s + ", Average: "+ average.to_s, [average], '000000'
-
end
-
end
-
i = i +1
-
end
-
puts "\nBar Chart"
-
@bc= bc.to_url
-
end
-
end
-
-
GoogleChart::BarChart.new("600x350"," ",:horizontal,false) do |bc|
-
bc.data " ", [100], 'ffffff'
-
bc.axis :x, :range => [min,max]
-
i = 0
-
@assignments.each do |assignment|
-
assignment_participant = assignment.participants.find_by_user_id(@current_student.user_id)
-
if !assignment_participant.nil?
-
meta_scores = assignment_participant.get_metareviews()
-
j = 1.to_i
-
average = 0;
-
if !meta_scores.nil?
-
meta_scores.each do |meta_score|
-
average = average + meta_score.get_average_score
-
bc.data assignment.name.to_s + ", Scores ".to_s + meta_score.get_average_score.to_s, [meta_score.get_average_score], colors[i]
-
j = j + 1
-
end
-
if( (j-1).to_i > 0)
-
average = average.to_i / (j-1).to_i
-
bc.data assignment.name.to_s + ", Average: "+ average.to_s, [average], '000000'
-
end
-
-
end
-
i = i +1
-
end
-
puts "\nBar Chart"
-
@mt= bc.to_url
-
end
-
end
-
end
-
-
1
def one_assignment_one_student
-
@assignment = Assignment.find_by_id(params[:assignment_id])
-
@participant = Participant.find_by_user_id(params[:user_id])
-
@questionnaires = @assignment.questionnaires
-
bar_1_data = [@participant.get_average_score]
-
bar_2_data = [Response.get_average_score(@assignment.id)]
-
color_1 = 'c53711'
-
color_2 = '0000ff'
-
min=0
-
max=100
-
-
GoogleChart::BarChart.new("500x100", " ", :horizontal, false) do |bc|
-
bc.data " ", [100], 'ffffff'
-
bc.data "Student", bar_1_data, color_1
-
bc.data "Class Average", bar_2_data, color_2
-
bc.axis :x, :range => [min,max]
-
bc.show_legend = true
-
bc.stacked = false
-
bc.data_encoding = :extended
-
@bc= bc.to_url
-
end
-
end
-
-
1
def all_assignments_one_student
-
-
end
-
-
end
-
#Author: Hao Liu
-
#Email: hliu11@ncsu.edu
-
-
1
class AssignmentQuestionnaireController < ApplicationController
-
#delete all AssignmentQuestionnaire entry that's associated with an assignment
-
1
def delete_all
-
assignment = Assignment.find(params[:assignment_id])
-
if assignment.nil?
-
return #TODO: add error message
-
end
-
-
@assignment_questionnaires = AssignmentQuestionnaire.find_all_by_assignment_id(params[:assignment_id])
-
@assignment_questionnaires.each do |assignment_questionnaire|
-
assignment_questionnaire.delete
-
end
-
-
respond_to do |format|
-
format.json { render :json => @assignment_questionnaires }
-
end
-
end
-
-
1
def create
-
if params[:assignment_id].nil? or params[:questionnaire_id].nil?
-
return #TODO: add error message
-
end
-
-
assignment = Assignment.find(params[:assignment_id])
-
if assignment.nil?
-
return #TODO: add error message
-
end
-
-
questionnaire = Questionnaire.find(params[:questionnaire_id])
-
if questionnaire.nil?
-
return #TODO: add error message
-
end
-
-
@assignment_questionnaire = AssignmentQuestionnaire.new(params)
-
@assignment_questionnaire.save
-
-
respond_to do |format|
-
format.json { render :json => @assignment_questionnaire }
-
end
-
end
-
end
-
1
class AssignmentSignupsController < ApplicationController
-
-
1
def index
-
list
-
render :action => 'list'
-
end
-
-
# GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
-
verify :method => :post, :only => [ :destroy, :create, :update ],
-
1
:redirect_to => { :action => :list }
-
-
1
def list
-
@assignment_signups = SignupSheet.find(:all)
-
end
-
-
1
def listuser
-
@user_id = session[:user].id
-
if (session[:user].role_id == 1)
-
@signups= SignupSheet.find_by_sql("select * from signup_sheets where assignment_id in (select assignment_id from participants where user_id = "+session[:user].id.to_s+")")
-
else
-
@signups= SignupSheet.find_by_sql("select * from signup_sheets")
-
end
-
end
-
-
1
def show
-
@assignment_signup = AssignmentSignup.find(params[:id])
-
end
-
-
1
def new
-
@assignment_signup = AssignmentSignup.new
-
@signup_sheets = SignupSheet.find(:all)
-
@assignments = Assignment.find_by_sql("select * from assignments where id not in (select assignment_id from assignment_signups where signup_id = "+@params[:id].to_s+")")
-
end
-
-
1
def create
-
@assignment_signup = AssignmentSignup.new(params[:assignment_signup])
-
@assignment_signup.assignment_id = params[:assignment_id]
-
@assignment_signup.signup_id = params[:signup_id]
-
-
if @assignment_signup.save
-
@assignments = Assignment.find_by_id(params[:assignment_id])
-
flash[:notice] = 'Assignment Signup was successfully created for assignment '+@assignments.name
-
redirect_to :controller => 'signup_sheets', :action => 'list'
-
else
-
@signup_sheets = SignupSheet.find(:all)
-
@assignments = Assignment.find(:all)
-
render :action => 'new'
-
end
-
end
-
-
1
def edit
-
@assignments = Assignment.find(:all)
-
@assignment_signup = AssignmentSignup.find(params[:id])
-
end
-
-
1
def update
-
-
@assignment_signup = AssignmentSignup.find(params[:id])
-
@assignment_signup.assignment_id = params[:assignment_id]
-
if @assignment_signup.update_attributes(params[:assignment_signup])
-
flash[:notice] = 'AssignmentSignup was successfully updated.'
-
redirect_to :action => 'show', :id => @assignment_signup
-
else
-
@assignments = Assignment.find(:all)
-
render :action => 'edit'
-
end
-
end
-
-
1
def destroy
-
AssignmentSignup.find(params[:id]).destroy
-
redirect_to :action => 'list'
-
end
-
end
-
1
class AssignmentsController < ApplicationController
-
1
auto_complete_for :user, :name
-
1
before_filter :authorize
-
-
# change access permission from public to private or vice versa
-
1
def toggle_access
-
assignment = Assignment.find(params[:id])
-
assignment.private = !assignment.private
-
assignment.save
-
redirect_to :controller => 'tree_display', :action => 'list'
-
end
-
-
1
def new
-
@assignment = Assignment.new
-
@assignment.course = Course.find(params[:parent_id]) if params[:parent_id]
-
-
@assignment.instructor = @assignment.course.instructor if @assignment.course
-
@assignment.instructor ||= current_user
-
-
@assignment.wiki_type_id = 1 #default no wiki type
-
@assignment.max_team_size = 1
-
end
-
-
1
def create
-
@assignment = Assignment.new(params[:assignment])
-
-
if @assignment.save
-
@assignment.create_node
-
flash[:success] = 'Assignment was successfully created.'
-
redirect_to controller: :assignments, action: :edit, id: @assignment.id
-
else
-
render 'new'
-
end
-
end
-
-
1
def edit
-
@assignment = Assignment.find(params[:id])
-
set_up
-
end
-
-
1
def delete_all_due_dates
-
if params[:assignment_id].nil?
-
return
-
end
-
-
assignment = Assignment.find(params[:assignment_id])
-
if assignment.nil?
-
return
-
end
-
-
@due_dates = DueDate.find_all_by_assignment_id(params[:assignment_id])
-
@due_dates.each do |due_date|
-
due_date.delete
-
end
-
-
respond_to do |format|
-
format.json { render :json => @due_dates }
-
end
-
end
-
-
1
def set_due_date
-
if params[:due_date][:assignment_id].nil?
-
return
-
end
-
-
assignment = Assignment.find(params[:due_date][:assignment_id])
-
if assignment.nil?
-
return
-
end
-
-
due_at = DateTime.parse(params[:due_date][:due_at])
-
if due_at.nil?
-
return
-
end
-
-
@due_date = DueDate.new(params[:due_date])
-
@due_date.save
-
-
respond_to do |format|
-
format.json { render :json => @due_date }
-
end
-
end
-
-
1
def delete_all_questionnaires
-
assignment = Assignment.find(params[:assignment_id])
-
if assignment.nil?
-
return
-
end
-
-
@assignment_questionnaires = AssignmentQuestionnaire.find_all_by_assignment_id(params[:assignment_id])
-
@assignment_questionnaires.each do |assignment_questionnaire|
-
assignment_questionnaire.delete
-
end
-
-
respond_to do |format|
-
format.json { render :json => @assignment_questionnaires }
-
end
-
end
-
-
1
def set_questionnaire
-
if params[:assignment_questionnaire][:assignment_id].nil? or params[:assignment_questionnaire][:questionnaire_id].nil?
-
return
-
end
-
-
assignment = Assignment.find(params[:assignment_questionnaire][:assignment_id])
-
if assignment.nil?
-
return
-
end
-
-
questionnaire = Questionnaire.find(params[:assignment_questionnaire][:questionnaire_id])
-
if questionnaire.nil?
-
return
-
end
-
-
@assignment_questionnaire = AssignmentQuestionnaire.new(params[:assignment_questionnaire])
-
@assignment_questionnaire.save
-
-
respond_to do |format|
-
format.json { render :json => @assignment_questionnaire }
-
end
-
end
-
-
-
1
def update
-
@assignment = Assignment.find(params[:id])
-
params[:assignment][:wiki_type_id] = 1 unless params[:assignment_wiki_assignment]
-
-
#TODO: require params[:assignment][:directory_path] to be not null
-
#TODO: insert warning if directory_path is duplicated
-
-
if @assignment.update_attributes(params[:assignment])
-
flash[:note] = 'Assignment was successfully saved.'
-
#TODO: deal with submission path change
-
# Need to rename the bottom-level directory and/or move intermediate directories on the path to an
-
# appropriate place
-
# Probably there are 2 different operations:
-
# - rename an assgt. -- implemented by renaming a directory
-
# - assigning an assignment to a course -- implemented by moving a directory.
-
-
redirect_to :action => 'edit', :id => @assignment.id
-
else
-
flash[:error] = 'Assignment save failed.'
-
redirect_to :action => 'edit', :id => @assignment.id
-
end
-
-
#respond_to do |format|
-
# format.json { render :json => params }
-
#end
-
end
-
-
1
def show
-
@assignment = Assignment.find(params[:id])
-
end
-
-
-
#NOTE: many of these functions actually belongs to other models
-
#====setup methods for new and edit method=====#
-
1
def set_up
-
set_up_defaults
-
-
submissions = @assignment.find_due_dates('submission') + @assignment.find_due_dates('resubmission')
-
reviews = @assignment.find_due_dates('review') + @assignment.find_due_dates('rereview')
-
@assignment.rounds_of_reviews = [@assignment.rounds_of_reviews, submissions.count, reviews.count].max
-
-
if @assignment.directory_path.try :empty?
-
@assignment.directory_path = nil
-
end
-
end
-
-
#NOTE: unfortunately this method is needed due to bad data in db @_@
-
1
def set_up_defaults
-
if @assignment.require_signup.nil?
-
@assignment.require_signup = false
-
end
-
if @assignment.wiki_type.nil?
-
@assignment.wiki_type = WikiType.find_by_name('No')
-
end
-
if @assignment.staggered_deadline.nil?
-
@assignment.staggered_deadline = false
-
@assignment.days_between_submissions = 0
-
end
-
if @assignment.availability_flag.nil?
-
@assignment.availability_flag = false
-
end
-
if @assignment.microtask.nil?
-
@assignment.microtask = false
-
end
-
if @assignment.reviews_visible_to_all.nil?
-
@assignment.reviews_visible_to_all = false
-
end
-
if @assignment.review_assignment_strategy.nil?
-
@assignment.review_assignment_strategy = ''
-
end
-
end
-
-
-
# this function finds all the due_dates for a given assignment and calculates the time when the reminder for these deadlines needs to be sent. Enqueues them in the delayed_jobs table
-
1
def add_to_delayed_queue
-
due_dates = @assignment.due_dates
-
due_dates.each do |due_date|
-
deadline_type_name = due_date.deadline_type.name
-
seconds_until_due = due_at - Time.now
-
minutes_until_due = seconds_until_due / 60
-
dj = Delayed::Job.enqueue(DelayedMailer.new(@assignment.id, deadline_type_name, due_at), 1, minutes_until_due)
-
due_date.update_attribute(:delayed_job_id, dj.id)
-
end
-
end
-
-
# Deletes the job with id equal to "delayed_job_id" from the delayed_jobs queue
-
1
def delete_from_delayed_queue(delayed_job_id)
-
dj=Delayed::Job.find(delayed_job_id)
-
if (dj != nil && dj.id != nil)
-
dj.delete
-
end
-
end
-
-
#--------------------------------------------------------------------------------------------------------------------
-
# GET_PATH (Helper function for CREATE and UPDATE)
-
# return the file location if there is any for the assignment
-
# TODO: to be depreicated
-
#--------------------------------------------------------------------------------------------------------------------
-
1
def get_path
-
begin
-
file_path = @assignment.get_path
-
rescue
-
file_path = nil
-
end
-
return file_path
-
end
-
-
-
#--------------------------------------------------------------------------------------------------------------------
-
# COPY_PARTICIPANTS_FROM_COURSE
-
# if assignment and course are given copy the course participants to assignment
-
# TODO: to be tested
-
#--------------------------------------------------------------------------------------------------------------------
-
1
def copy_participants_from_course
-
if params[:assignment][:course_id]
-
begin
-
Course.find(params[:assignment][:course_id]).copy_participants(params[:id])
-
rescue
-
flash[:error] = $!
-
end
-
end
-
end
-
-
#-------------------------------------------------------------------------------------------------------------------
-
# COPY
-
# Creates a copy of an assignment along with dates and submission directory
-
# TODO: need to be tested
-
#-------------------------------------------------------------------------------------------------------------------
-
1
def copy
-
Assignment.record_timestamps = false
-
old_assign = Assignment.find(params[:id])
-
new_assign = old_assign.clone
-
@user = ApplicationHelper::get_user_role(session[:user])
-
@user = session[:user]
-
@user.set_instructor(new_assign)
-
new_assign.update_attribute('name', 'Copy of ' + new_assign.name)
-
new_assign.update_attribute('created_at', Time.now)
-
new_assign.update_attribute('updated_at', Time.now)
-
-
if new_assign.directory_path.present?
-
new_assign.update_attribute('directory_path', new_assign.directory_path + '_copy')
-
end
-
-
session[:copy_flag] = true
-
new_assign.copy_flag = true
-
-
if new_assign.save
-
Assignment.record_timestamps = true
-
-
old_assign.assignment_questionnaires.each do |aq|
-
AssignmentQuestionnaire.create(
-
:assignment_id => new_assign.id,
-
:questionnaire_id => aq.questionnaire_id,
-
:user_id => session[:user].id,
-
:notification_limit => aq.notification_limit,
-
:questionnaire_weight => aq.questionnaire_weight
-
)
-
end
-
-
DueDate.copy(old_assign.id, new_assign.id)
-
new_assign.create_node()
-
-
flash[:note] = 'Warning: The submission directory for the copy of this assignment will be the same as the submission directory for the existing assignment, which will allow student submissions to one assignment to overwrite submissions to the other assignment. If you do not want this to happen, change the submission directory in the new copy of the assignment.'
-
-
redirect_to :action => 'edit', :id => new_assign.id
-
else
-
flash[:error] = 'The assignment was not able to be copied. Please check the original assignment for missing information.'
-
redirect_to :action => 'list', :controller => 'tree_display'
-
end
-
end
-
-
-
#--------------------------------------------------------------------------------------------------------------------
-
# DELETE
-
# TODO: not been cleanup yep
-
#--------------------------------------------------------------------------------------------------------------------
-
1
def delete
-
assignment = Assignment.find(params[:id])
-
-
# If the assignment is already deleted, go back to the list of assignments
-
if assignment
-
begin
-
#delete from delayed_jobs queue
-
djobs = Delayed::Job.find(:all, :conditions => ['handler LIKE "%assignment_id: ?%"', assignment.id])
-
for dj in djobs
-
delete_from_delayed_queue(dj.id)
-
end
-
-
@user = session[:user]
-
id = @user.get_instructor
-
if (id != assignment.instructor_id)
-
raise "Not authorised to delete this assignment"
-
end
-
assignment.delete(params[:force])
-
@a = Node.find(:first, :conditions => ['node_object_id = ? and type = ?', params[:id], 'AssignmentNode'])
-
-
@a.destroy
-
flash[:notice] = "The assignment is deleted"
-
rescue
-
url_yes = url_for :action => 'delete', :id => params[:id], :force => 1
-
url_no = url_for :action => 'delete', :id => params[:id]
-
error = $!
-
flash[:error] = error.to_s + " Delete this assignment anyway? <a href='#{url_yes}'>Yes</a> | <a href='#{url_no}'>No</a><BR/>"
-
end
-
end
-
-
redirect_to :controller => 'tree_display', :action => 'list'
-
end
-
-
1
def list
-
set_up_display_options("ASSIGNMENT")
-
@assignments=super(Assignment)
-
# @assignment_pages, @assignments = paginate :assignments, :per_page => 10
-
end
-
-
-
#--------------------------------------------------------------------------------------------------------------------
-
# DEFINE_INSTRUCTOR_NOTIFICATION_LIMIT
-
# TODO: NO usages found need verification
-
#--------------------------------------------------------------------------------------------------------------------
-
1
def define_instructor_notification_limit(assignment_id, questionnaire_id, limit)
-
existing = NotificationLimit.find(:first, :conditions => ['user_id = ? and assignment_id = ? and questionnaire_id = ?', session[:user].id, assignment_id, questionnaire_id])
-
if existing.nil?
-
NotificationLimit.create(:user_id => session[:user].id,
-
:assignment_id => assignment_id,
-
:questionnaire_id => questionnaire_id,
-
:limit => limit)
-
else
-
existing.limit = limit
-
existing.save
-
end
-
end
-
-
1
def associate_assignment_to_course
-
puts '>>>>' + params[:id].to_s
-
@assignment = Assignment.find(params[:id])
-
@assignment.inspect
-
@user = ApplicationHelper::get_user_role(session[:user])
-
@user = session[:user]
-
@courses = @user.set_courses_to_assignment
-
end
-
-
1
def remove_assignment_from_course
-
assignment = Assignment.find(params[:id])
-
oldpath = assignment.get_path rescue nil
-
assignment.course_id = nil
-
assignment.save
-
newpath = assignment.get_path rescue nil
-
FileHelper.update_file_location(oldpath, newpath)
-
redirect_to :controller => 'tree_display', :action => 'list'
-
end
-
-
end
-
1
class AuthController < ApplicationController
-
1
helper :auth
-
1
before_filter :authorize, :except => :login
-
-
# GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
-
verify :method => :post, :only => [ :login, :logout ],
-
1
:redirect_to => { :action => :list }
-
-
1
def login
-
11
if request.get?
-
AuthController.clear_session(session)
-
else
-
11
user = User.find_by_login(params[:login][:name])
-
-
11
if user and user.valid_password?(params[:login][:password])
-
11
logger.info "User #{params[:login][:name]} successfully logged in"
-
11
session[:user] = user
-
11
AuthController.set_current_role(user.role_id, session)
-
-
11
redirect_to :controller => AuthHelper::get_home_controller(session[:user]), :action => AuthHelper::get_home_action(session[:user])
-
else
-
logger.warn "Failed login attempt"
-
flash[:error] = "Incorrect Name/Password"
-
redirect_to :controller => 'password_retrieval', :action => 'forgotten'
-
end
-
end
-
end # def login
-
-
1
def login_failed
-
flash.now[:error] = "Incorrect Name/Password"
-
render :action => 'forgotten'
-
end
-
-
1
def logout
-
AuthController.logout(session)
-
redirect_to '/'
-
end
-
-
1
def self.authorised?(session, params)
-
authorised = false # default
-
check_controller = false
-
-
if params[:controller] == 'content_pages' and
-
params[:action] == 'view'
-
if session[:credentials].pages.has_key?(params[:page_name].to_s)
-
if session[:credentials].pages[params[:page_name].to_s] == true
-
logger.info "Page: authorised"
-
authorised = true
-
else
-
logger.info "Page: NOT authorised"
-
end
-
else
-
logger.warn "(Unknown page? #{params[:page_name].to_s})"
-
end
-
else
-
# Check if there's a specific permission for an action
-
if session[:credentials].actions.has_key?(params[:controller])
-
if session[:credentials].actions[params[:controller]].has_key?(params[:action])
-
if session[:credentials].actions[params[:controller]][params[:action]]
-
logger.info "Action: authorised"
-
authorised = true
-
else
-
logger.info "Action: NOT authorised"
-
end
-
else
-
check_controller = true
-
end
-
else
-
check_controller = true
-
end
-
-
# Check if there's a general permission for a controller
-
if check_controller
-
if session[:credentials].controllers.has_key?(params[:controller])
-
if session[:credentials].controllers[params[:controller]]
-
logger.info "Controller: authorised"
-
authorised = true
-
else
-
logger.info "Controller: NOT authorised"
-
end
-
else
-
end
-
end
-
end # Check permissions
-
-
logger.info "Authorised? #{authorised.to_s}"
-
return authorised
-
end
-
-
-
1
protected
-
-
1
def self.logout(session)
-
self.clear_session(session)
-
end
-
-
1
def self.set_current_role(role_id, session)
-
11
if role_id
-
11
role = Role.find role_id
-
11
if role
-
11
if !role.cache || !role.cache.try(:has_key?, :credentials)
-
Role.rebuild_cache
-
end
-
11
session[:credentials] = role.cache[:credentials]
-
11
session[:menu] = role.cache[:menu]
-
11
logger.info "Logging in user as role #{session[:credentials].class}"
-
else
-
logger.error "Something went seriously wrong with the role"
-
end
-
end
-
end
-
-
1
def self.clear_session(session)
-
session[:user_id] = nil
-
session[:user] = nil
-
session[:credentials] = nil
-
session[:menu] = nil
-
session[:clear] = true
-
session[:assignment_id] = nil
-
end
-
-
#clears any identifying info from session
-
1
def self.clear_user_info(session, assignment_id)
-
session[:user_id] = nil
-
session[:user] = "" #sets user to an empty string instead of nil, to show that the user was logged in
-
role = Role.student
-
if role
-
if not role.cache or not role.cache.has_key?(:credentials)
-
Role.rebuild_cache
-
end
-
session[:credentials] = role.cache[:credentials]
-
session[:menu] = role.cache[:menu]
-
end
-
session[:clear] = true
-
session[:assignment_id] = assignment_id
-
end
-
-
end
-
1
class AutomatedMetareviewsController < ApplicationController
-
1
attr_accessor :automated_metareviews
-
1
def index
-
@automated_metareviews = AutomatedMetareview.all
-
respond_to do |format|
-
format.html # index.html.erb
-
format.xml { render :xml => @automated_metareviews }
-
end
-
end
-
-
1
def list
-
@automated_metareview = AutomatedMetareview.new
-
#pass in the response id as a parameter
-
@response = Response.find_by_map_id(params[:id])
-
@automated_metareview.calculate_metareview_metrics(@response, params[:id])
-
if @automated_metareview.save!
-
flash[:notice] = 'Automated Metareview Saved!'
-
puts "SAVED SUCESSFULLY - #{@automated_metareview.response_id}"
-
else
-
flash[:error] = 'Automated Metareview Not Saved'
-
puts "NOT SAVED!"
-
end
-
-
#fetching average metrics values
-
avg_existing_metareviews = AutomatedMetareview.find_by_sql(["select avg(relevance) as relevance, avg(content_summative) as summative,
-
avg(content_problem) as problem, avg(content_advisory) as advisory, avg(tone_positive) as positive, avg(tone_negative) as negative,
-
avg(tone_neutral) as neutral, avg(quantity) as quantity from automated_metareviews where response_id <> ?", @automated_metareview.response_id])[0]
-
puts "avg_existing_metareviews #{avg_existing_metareviews}"
-
if(!avg_existing_metareviews.nil?)
-
#if any of the values are -ve, set them as 0 (for graph display)
-
if(avg_existing_metareviews.relevance.nil? or avg_existing_metareviews.relevance < 0)
-
avg_existing_metareviews.relevance = 0
-
end
-
if(avg_existing_metareviews.summative.nil? or avg_existing_metareviews.summative.to_f < 0)
-
avg_existing_metareviews.summative = 0
-
end
-
if(avg_existing_metareviews.problem.nil? or avg_existing_metareviews.problem.to_f < 0)
-
avg_existing_metareviews.problem = 0
-
end
-
if(avg_existing_metareviews.advisory.nil? or avg_existing_metareviews.advisory.to_f < 0)
-
avg_existing_metareviews.advisory = 0
-
end
-
if(avg_existing_metareviews.positive.nil? or avg_existing_metareviews.positive.to_f < 0)
-
avg_existing_metareviews.positive = 0
-
end
-
if(avg_existing_metareviews.negative.nil? or avg_existing_metareviews.negative.to_f < 0)
-
avg_existing_metareviews.negative = 0
-
end
-
if(avg_existing_metareviews.neutral.nil? or avg_existing_metareviews.neutral.to_f < 0)
-
avg_existing_metareviews.neutral = 0
-
end
-
end
-
-
-
#for current metareview values
-
if(@automated_metareview.relevance.to_f < 0)
-
@automated_metareview.relevance = 0
-
end
-
if(@automated_metareview.content_summative.to_f < 0)
-
@automated_metareview.content_summative = 0
-
end
-
if(@automated_metareview.content_problem.to_f < 0)
-
@automated_metareview.content_problem = 0
-
end
-
if(@automated_metareview.content_advisory.to_f < 0)
-
@automated_metareview.content_advisory = 0
-
end
-
if(@automated_metareview.tone_positive.to_f < 0)
-
@automated_metareview.tone_positive = 0
-
end
-
if(@automated_metareview.tone_negative.to_f < 0)
-
@automated_metareview.tone_negative = 0
-
end
-
if(@automated_metareview.tone_neutral.to_f < 0)
-
@automated_metareview.tone_neutral = 0
-
end
-
#creating the arrays to be graphed
-
current_metareview_data = [@automated_metareview.relevance.to_f, @automated_metareview.content_summative.to_f ,
-
@automated_metareview.content_problem.to_f, @automated_metareview.content_advisory.to_f, @automated_metareview.tone_positive.to_f,
-
@automated_metareview.tone_negative.to_f, @automated_metareview.tone_neutral.to_f]
-
-
existing_metareview_data = [avg_existing_metareviews.relevance.to_f, avg_existing_metareviews.summative.to_f,
-
avg_existing_metareviews.problem.to_f, avg_existing_metareviews.advisory.to_f, avg_existing_metareviews.positive.to_f,
-
avg_existing_metareviews.negative.to_f, avg_existing_metareviews.neutral.to_f]
-
-
color_1 = 'c53711'
-
color_2 = '0000ff'
-
#labels in reverse order of content being displayed
-
names_array = ["Neutral Tone", "Negative Tone", "Positive Tone", "Advisory Content", "Problem Content", "Summative Content", "Relevance"]
-
GoogleChart::BarChart.new("500x450", "Your work Vs Average performance on reviews", :horizontal, false) do |bc|
-
bc.data "Your work", current_metareview_data, color_1
-
bc.data "Avg. performance on reviews", existing_metareview_data, color_2
-
bc.axis :y, :labels => names_array, :font_size => 10
-
bc.axis :x, :range => [0,1]
-
bc.show_legend = true
-
bc.stacked = false
-
bc.data_encoding = :extended
-
bc.shape_marker :circle, :color => '00ff00', :data_set_index => 0, :data_point_index => -1, :pixel_size => 10
-
#puts bc.to_url
-
@graph = bc.to_url
-
end
-
end
-
end
-
1
class ContentPagesController < ApplicationController
-
-
# GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
-
verify :method => :post, :only => [ :destroy, :create, :update ],
-
1
:redirect_to => { :action => :list }
-
-
1
def index
-
list
-
render :action => 'list'
-
end
-
-
1
def list
-
@content_pages = ContentPage.find(:all,
-
:order => 'name')
-
end
-
-
1
def show
-
@content_page = ContentPage.find(params[:id])
-
foreign
-
end
-
-
1
def view
-
11
@content_page = ContentPage.find_by_name(params[:page_name])
-
11
if not @content_page
-
if @settings
-
@content_page = ContentPage.find(@settings.not_found_page_id)
-
else
-
@content_page = ContentPage.new(:id => nil,
-
:content => '(no such page)')
-
end
-
end
-
end
-
-
1
def view_default
-
if @settings
-
@content_page = ContentPage.find(@settings.site_default_page_id)
-
else
-
@content_page = ContentPage.new(:id => nil,
-
:content => '(Site not configured)')
-
end
-
end
-
-
1
def new
-
@content_page = ContentPage.new
-
foreign
-
end
-
-
1
def create
-
@content_page = ContentPage.new(params[:content_page])
-
begin
-
@content_page.save!
-
flash[:notice] = 'ContentPage was successfully created.'
-
Role.rebuild_cache
-
redirect_to :action => 'list'
-
rescue
-
foreign
-
-
render :action => 'new'
-
end
-
end
-
-
1
def edit
-
@content_page = ContentPage.find(params[:id])
-
foreign()
-
end
-
-
1
def update
-
@content_page = ContentPage.find(params[:id])
-
if @content_page.update_attributes(params[:content_page])
-
flash[:notice] = 'ContentPage was successfully updated.'
-
Role.rebuild_cache
-
redirect_to :action => 'show', :id => @content_page
-
else
-
foreign
-
render :action => 'edit'
-
end
-
end
-
-
1
def destroy
-
@content_page = ContentPage.find(params[:id])
-
foreign
-
-
if @menu_items.length == 0 and not @system_pages
-
@content_page.destroy
-
Role.rebuild_cache
-
redirect_to :action => 'list'
-
else
-
flash.now[:error] = "Cannot delete this Content Page as it has dependants (see below)"
-
render :action => 'show'
-
end
-
end
-
-
-
1
protected
-
-
1
def foreign
-
@markup_styles = MarkupStyle.find(:all, :order => 'name')
-
@permissions = Permission.find(:all, :order => 'name')
-
if @content_page.id
-
@menu_items = MenuItem.find(:all,
-
:order => 'label',
-
:conditions => ['content_page_id=?',
-
@content_page.id])
-
@system_pages = @settings.system_pages @content_page.id
-
end
-
end
-
-
-
end
-
1
class ControllerActionsController < ApplicationController
-
-
# GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
-
verify :method => :post, :only => [ :destroy, :create, :update ],
-
1
:redirect_to => { :action => :index }
-
-
-
1
def index
-
@controller_actions = ControllerAction.order(:name).paginate(per_page: 50, page: 1)
-
end
-
-
-
1
def list
-
redirect_to :action => 'index'
-
end
-
-
-
1
def show
-
@controller_action = ControllerAction.find(params[:id])
-
@permission = @controller_action.permission || Permission.new(:id => nil, :name => '(default)')
-
end
-
-
-
1
def new
-
@controller_action = ControllerAction.new
-
foreign
-
end
-
-
-
1
def new_for
-
@controller_action = ControllerAction.new
-
@controller_action.site_controller_id = params[:id]
-
@site_controller = SiteController.find(params[:id])
-
if @site_controller
-
@actions = class_actions(@site_controller.name)
-
end
-
foreign
-
render :action => 'new'
-
end
-
-
-
1
def create
-
if params[:controller_action][:specific_name] and
-
params[:controller_action][:specific_name].length > 0
-
params[:controller_action][:name] =
-
params[:controller_action][:specific_name]
-
end
-
@controller_action = ControllerAction.new(params[:controller_action])
-
if @controller_action.save
-
flash[:notice] = 'ControllerAction was successfully created.'
-
Role.rebuild_cache
-
redirect_to :controller => 'site_controllers', :action => 'show',
-
:id => @controller_action.site_controller_id
-
else
-
foreign
-
render :action => 'new'
-
end
-
end
-
-
-
1
def edit
-
@controller_action = ControllerAction.find(params[:id])
-
foreign
-
end
-
-
-
1
def update
-
@controller_action = ControllerAction.find(params[:id])
-
if @controller_action.update_attributes(params[:controller_action])
-
flash[:notice] = 'ControllerAction was successfully updated.'
-
Role.rebuild_cache
-
redirect_to :controller => 'site_controllers', :action => 'show',
-
:id => @controller_action.site_controller_id
-
else
-
foreign
-
render :action => 'edit'
-
end
-
end
-
-
-
1
def destroy
-
@controller_action = ControllerAction.find(params[:id])
-
site_controller_id = @controller_action.site_controller_id
-
@controller_action.destroy
-
Role.rebuild_cache
-
redirect_to @controller_action.site_controller
-
end
-
-
1
protected
-
-
1
def foreign
-
@controllers = SiteController.order :name
-
-
@permissions = Permission.order :name
-
@permissions.unshift Permission.new(:id => nil, :name => '(default)')
-
end
-
-
-
1
def class_actions(classname)
-
classes = SiteController.classes
-
actions = Hash.new()
-
-
if classes.has_key? classname
-
controller = classes[classname]
-
-
for method in controller.public_instance_methods(false) do
-
actions[method] = true
-
end
-
-
for hidden in controller.hidden_actions do
-
actions.delete hidden
-
end
-
end
-
-
action_collection = Array.new
-
for action in actions.keys.sort do
-
action_collection << ControllerAction.new(:name => action)
-
end
-
-
return action_collection
-
end
-
-
end
-
# Provides Course functions
-
# Author: unknown
-
#
-
# Last modified: 7/18/2008
-
# By: ajbudlon
-
1
class CourseController < ApplicationController
-
1
auto_complete_for :user, :name
-
1
require 'fileutils'
-
-
1
def auto_complete_for_user_name
-
search = params[:user][:name].to_s
-
@users = User.find_by_sql("select * from users where role_id=6") unless search.blank?
-
render :inline => "<%= auto_complete_result @users, 'name' %>", :layout => false
-
end
-
# Creates a new course
-
# if private is set to 1, then the course will
-
# only be available to the instructor who created it.
-
1
def new
-
@private = params[:private]
-
end
-
-
# Modify an existing course
-
1
def edit
-
@course = Course.find(params[:id])
-
end
-
-
1
def update
-
course = Course.find(params[:id])
-
if params[:course][:directory_path] and course.directory_path != params[:course][:directory_path]
-
begin
-
FileHelper.delete_directory(course)
-
rescue
-
flash[:error] = $!
-
end
-
-
begin
-
FileHelper.create_directory_from_path(params[:course][:directory_path])
-
rescue
-
flash[:error] = $!
-
end
-
end
-
course.update_attributes(params[:course])
-
redirect_to :controller => 'tree_display', :action => 'list'
-
end
-
-
1
def copy
-
orig_course = Course.find(params[:id])
-
new_course = orig_course.clone
-
new_course.instructor_id = session[:user].id
-
new_course.name = 'Copy of '+orig_course.name
-
begin
-
new_course.save!
-
parent_id = CourseNode.get_parent_id
-
if parent_id
-
CourseNode.create(:node_object_id => new_course.id, :parent_id => parent_id)
-
else
-
CourseNode.create(:node_object_id => new_course.id)
-
end
-
-
flash[:note] = 'The course is currently associated with an existing location. This could cause errors for furture submissions.'
-
redirect_to :controller => 'course', :action => 'edit', :id => new_course.id
-
rescue
-
flash[:error] = 'The course was not able to be copied: '+$!
-
redirect_to :controller => 'tree_display', :action => 'list'
-
end
-
end
-
-
# create a course
-
1
def create
-
course = Course.new(params[:course])
-
-
course.instructor_id = session[:user].id
-
begin
-
course.save!
-
parent_id = CourseNode.get_parent_id
-
if parent_id
-
CourseNode.create(:node_object_id => course.id, :parent_id => parent_id)
-
else
-
CourseNode.create(:node_object_id => course.id)
-
end
-
FileHelper.create_directory(course)
-
redirect_to :controller => 'tree_display', :action => 'list'
-
rescue
-
flash[:error] = "The following error occurred while saving the course: "+$!
-
redirect_to :action => 'new'
-
end
-
end
-
-
# delete the course
-
1
def delete
-
course = Course.find(params[:id])
-
begin
-
FileHelper.delete_directory(course)
-
rescue
-
flash[:error] = $!
-
end
-
CourseNode.find_by_node_object_id(course.id).destroy
-
course.ta_mappings.each{
-
| map |
-
map.destroy
-
}
-
course.destroy
-
redirect_to :controller => 'tree_display', :action => 'list'
-
end
-
-
1
def toggle_access
-
course = Course.find(params[:id])
-
course.private = !course.private
-
begin
-
course.save!
-
rescue
-
flash[:error] = $!
-
end
-
redirect_to :controller => 'tree_display', :action => 'list'
-
end
-
-
1
def view_teaching_assistants
-
@course = Course.find(params[:id])
-
@ta_mappings = @course.ta_mappings
-
for mapping in @ta_mappings
-
mapping[:name] = mapping.ta.name
-
end
-
end
-
-
1
def add_ta
-
@course = Course.find(params[:course_id])
-
@user = User.find_by_name(params[:user][:name])
-
if(@user==nil)
-
redirect_to :action => 'view_teaching_assistants', :id => @course.id
-
else
-
@ta_mapping = TaMapping.create(:ta_id => @user.id, :course_id => @course.id)
-
redirect_to :action => 'view_teaching_assistants', :id => @course.id
-
end
-
end
-
-
1
def remove_ta
-
@ta_mapping = TaMapping.find(params[:id])
-
@ta_mapping.destroy
-
redirect_to :action => 'view_teaching_assistants', :id => @ta_mapping.course
-
end
-
-
end
-
1
class CourseEvaluationController < ApplicationController
-
-
1
def list #list course evaluations for a user
-
unless session[:user] #Check for a valid user
-
redirect_to '/'
-
return
-
end
-
deployments=SurveyParticipant.find_all_by_user_id(session[:user].id)
-
@surveys=Array.new
-
deployments.each do |sd|
-
survey_deployment=SurveyDeployment.find(sd.survey_deployment_id)
-
if(Time.now>survey_deployment.start_date && Time.now<survey_deployment.end_date)
-
@surveys<<[Questionnaire.find(survey_deployment.course_evaluation_id),sd.survey_deployment_id,survey_deployment.end_date, survey_deployment.course_id]
-
end
-
end
-
end
-
-
end
-
#Author: Hao Liu
-
#Email: hliu11@ncsu.edu
-
#created at: May, 28, 2013
-
#update at: May, 28, 2013
-
-
1
class DueDateController < ApplicationController
-
-
1
def delete_all
-
if params[:assignment_id].nil?
-
return #TODO: add error message
-
end
-
-
assignment = Assignment.find(params[:assignment_id])
-
if assignment.nil?
-
return #TODO: add error message
-
end
-
-
@due_dates = DueDate.find_all_by_assignment_id(params[:assignment_id])
-
@due_dates.each do |due_date|
-
due_date.delete
-
end
-
-
respond_to do |format|
-
format.json { render :json => @due_dates }
-
end
-
end
-
-
1
def create
-
if params[:assignment_id].nil?
-
return #TODO: add error message
-
end
-
-
assignment = Assignment.find(params[:assignment_id])
-
if assignment.nil?
-
return #TODO: add error message
-
end
-
-
due_at = DateTime.parse(params[:due_at])
-
if due_at.nil?
-
return #TODO: add error message
-
end
-
-
@due_date = DueDate.new(params)
-
@due_date.save
-
-
respond_to do |format|
-
format.json { render :json => @due_date }
-
end
-
end
-
end
-
1
class EulaController < ApplicationController
-
1
def display
-
end
-
-
1
def accept
-
session[:user].update_attribute('is_new_user',0)
-
redirect_to :controller => 'student_task', :action => 'list'
-
end
-
-
1
def decline
-
flash[:notice] = 'Please accept the license agreement in order to use the system.'
-
redirect_to :action => 'display'
-
end
-
end
-
1
class ExportFileController < ApplicationController
-
1
require 'fastercsv'
-
-
1
def start
-
@model = params[:model]
-
if(@model == 'Assignment')
-
@title = 'Grades'
-
elsif(@model == 'CourseParticipant')
-
@title = 'Course Participants'
-
elsif(@model == 'AssignmentTeam')
-
@title = 'Teams'
-
elsif(@model == 'CourseTeam')
-
@title = 'Teams'
-
elsif(@model == 'User')
-
@title = 'Users'
-
end
-
@id = params[:id]
-
end
-
-
1
def export
-
@delim_type = params[:delim_type]
-
-
if(@delim_type == "comma")
-
filename = "out.csv"
-
delimiter = ","
-
elsif(@delim_type == "space")
-
filename = "out.csv"
-
delimiter = " "
-
elsif(@delim_type == "tab")
-
filename = "out.tsv"
-
delimiter = "\t"
-
elsif(@delim_type == "other")
-
filename = "out.txt"
-
delimiter = other_char
-
end
-
csv_data = FasterCSV.generate(:col_sep => delimiter) do |csv|
-
csv << Object.const_get(params[:model]).get_export_fields(params[:options])
-
-
Object.const_get(params[:model]).export(csv, params[:id],params[:options])
-
end
-
-
send_data csv_data,
-
:type => 'text/csv; charset=iso-8859-1; header=present',
-
:disposition => "attachment; filename=#{filename}"
-
end
-
end
-
1
class GradesController < ApplicationController
-
1
helper :file
-
1
helper :submitted_content
-
-
#the view grading report provides the instructor with an overall view of all the grades for
-
#an assignment. It lists all participants of an assignment and all the reviews they received.
-
#It also gives a final score, which is an average of all the reviews and greatest difference
-
#in the scores of all the reviews.
-
1
def view
-
@assignment = Assignment.find(params[:id])
-
@questions = Hash.new
-
questionnaires = @assignment.questionnaires
-
questionnaires.each {
-
|questionnaire|
-
@questions[questionnaire.symbol] = questionnaire.questions
-
}
-
@scores = @assignment.get_scores(@questions)
-
end
-
-
1
def view_my_scores
-
@participant = AssignmentParticipant.find(params[:id])
-
return if redirect_when_disallowed
-
@assignment = @participant.assignment
-
@questions = Hash.new
-
questionnaires = @assignment.questionnaires
-
questionnaires.each {
-
|questionnaire|
-
@questions[questionnaire.symbol] = questionnaire.questions
-
}
-
-
## When user clicks on the notification, it should go away
-
#deleting all review notifications
-
rmaps = @participant.response_maps
-
for rmap in rmaps
-
rmap.notification_accepted = true
-
rmap.save
-
end
-
############
-
-
#deleting all metareview notifications
-
rmaps = ParticipantReviewResponseMap.find_all_by_reviewer_id_and_reviewed_object_id(@participant.id, @participant.parent_id)
-
for rmap in rmaps
-
mmaps = MetareviewResponseMap.find_all_by_reviewee_id_and_reviewed_object_id(rmap.reviewer_id, rmap.id)
-
if !mmaps.nil?
-
for mmap in mmaps
-
mmap.notification_accepted = true
-
mmap.save
-
end
-
end
-
end
-
end
-
-
1
def edit
-
@participant = AssignmentParticipant.find(params[:id])
-
@assignment = @participant.assignment
-
@questions = Hash.new
-
questionnaires = @assignment.questionnaires
-
questionnaires.each {
-
|questionnaire|
-
@questions[questionnaire.symbol] = questionnaire.questions
-
}
-
-
@scores = @participant.get_scores(@questions)
-
end
-
-
1
def instructor_review
-
participant = AssignmentParticipant.find(params[:id])
-
-
reviewer = AssignmentParticipant.find_by_user_id_and_parent_id(session[:user].id, participant.assignment.id)
-
if reviewer.nil?
-
reviewer = AssignmentParticipant.create(:user_id => session[:user].id, :parent_id => participant.assignment.id)
-
reviewer.set_handle()
-
end
-
-
if participant.assignment.team_assignment?
-
reviewee = participant.team
-
review_mapping = TeamReviewResponseMap.find_by_reviewee_id_and_reviewer_id(reviewee.id, reviewer.id)
-
else
-
reviewee = participant
-
review_mapping = ParticipantReviewResponseMap.find_by_reviewee_id_and_reviewer_id(reviewee.id, reviewer.id)
-
end
-
-
if review_mapping.nil?
-
if participant.assignment.team_assignment?
-
review_mapping = TeamReviewResponseMap.create(:reviewee_id => participant.team.id, :reviewer_id => reviewer.id, :reviewed_object_id => participant.assignment.id)
-
else
-
review_mapping = ParticipantReviewResponseMap.create(:reviewee_id => participant.id, :reviewer_id => reviewer.id, :reviewed_object_id => participant.assignment.id)
-
end
-
end
-
review = Response.find_by_map_id(review_mapping.id)
-
-
if review.nil?
-
redirect_to :controller => 'response', :action => 'new', :id => review_mapping.id, :return => "instructor"
-
else
-
redirect_to :controller => 'response', :action => 'edit', :id => review.id, :return => "instructor"
-
end
-
end
-
-
1
def open
-
send_file(params['fname'], :disposition => 'inline')
-
end
-
-
-
1
def send_grading_conflict_email
-
email_form = params[:mailer]
-
assignment = Assignment.find(email_form[:assignment])
-
recipient = User.find(:first, :conditions => ["email = ?", email_form[:recipients]])
-
-
body_text = email_form[:body_text]
-
body_text["##[recipient_name]"] = recipient.fullname
-
body_text["##[recipients_grade]"] = email_form[recipient.fullname+"_grade"]+"%"
-
body_text["##[assignment_name]"] = assignment.name
-
-
Mailer.deliver_message(
-
{:recipients => email_form[:recipients],
-
:subject => email_form[:subject],
-
:from => email_form[:from],
-
:body => {
-
:body_text => body_text,
-
:partial_name => "grading_conflict"
-
}
-
}
-
)
-
-
flash[:notice] = "Your email to " + email_form[:recipients] + " has been sent. If you would like to send an email to another student please do so now, otherwise click Back"
-
redirect_to :action => 'conflict_email_form',
-
:assignment => email_form[:assignment],
-
:author => email_form[:author]
-
end
-
-
# the grading conflict email form provides the instructor a way of emailing
-
# the reviewers of a submission if he feels one of the reviews was unfair or inaccurate.
-
1
def conflict_notification
-
if session[:user].role_id !=6
-
@instructor = session[:user]
-
else
-
@instructor = Ta.get_my_instructor(session[:user].id)
-
end
-
@participant = AssignmentParticipant.find(params[:id])
-
@assignment = Assignment.find(@participant.parent_id)
-
-
-
@questions = Hash.new
-
questionnaires = @assignment.questionnaires
-
questionnaires.each {
-
|questionnaire|
-
@questions[questionnaire.symbol] = questionnaire.questions
-
}
-
-
@reviewers_email_hash = Hash.new
-
-
@caction = "view"
-
@submission = params[:submission]
-
if @submission == "review"
-
@caction = "view_review"
-
@symbol = "review"
-
process_response("Review", "Reviewer", @participant.get_reviews, "ReviewQuestionnaire")
-
elsif @submission == "review_of_review"
-
@symbol = "metareview"
-
process_response("Metareview", "Metareviewer", @participant.get_metareviews, "MetareviewQuestionnaire")
-
elsif @submission == "review_feedback"
-
@symbol = "feedback"
-
process_response("Feedback", "Author", @participant.get_feedback, "AuthorFeedbackQuestionnaire")
-
elsif @submission == "teammate_review"
-
@symbol = "teammate"
-
process_response("Teammate Review", "Reviewer", @participant.get_teammate_reviews, "TeammateReviewQuestionnaire")
-
end
-
-
@subject = " Your "+@collabel.downcase+" score for " + @assignment.name + " conflicts with another "+@rowlabel.downcase+"'s score."
-
@body = get_body_text(params[:submission])
-
-
end
-
-
-
1
def update
-
participant = AssignmentParticipant.find(params[:id])
-
total_score = params[:total_score]
-
if sprintf("%.2f", total_score) != params[:participant][:grade]
-
participant.update_attribute('grade', params[:participant][:grade])
-
if participant.grade.nil?
-
message = "The computed score will be used for "+participant.user.name
-
else
-
message = "A score of "+params[:participant][:grade]+"% has been saved for "+participant.user.name
-
end
-
end
-
flash[:note] = message
-
redirect_to :action => 'edit', :id => params[:id]
-
end
-
-
1
private
-
-
1
def process_response(collabel, rowlabel, responses, questionnaire_type)
-
@collabel = collabel
-
@rowlabel = rowlabel
-
@reviews = responses
-
@reviews.each {
-
|response|
-
user = response.map.reviewer.user
-
@reviewers_email_hash[user.fullname.to_s+" <"+user.email.to_s+">"] = user.email.to_s
-
}
-
@reviews.sort! { |a, b| a.map.reviewer.user.fullname <=> b.map.reviewer.user.fullname }
-
@questionnaire = @assignment.questionnaires.find_by_type(questionnaire_type)
-
@max_score, @weight = @assignment.get_max_score_possible(@questionnaire)
-
end
-
-
1
def redirect_when_disallowed
-
# For author feedback, participants need to be able to read feedback submitted by other teammates.
-
# If response is anything but author feedback, only the person who wrote feedback should be able to see it.
-
## This following code was cloned from response_controller.
-
-
#ACS Check if team count is more than 1 instead of checking if it is a team assignment
-
if @participant.assignment.max_team_size > 1
-
team = @participant.team
-
if(!team.nil?)
-
unless team.has_user session[:user]
-
redirect_to '/denied?reason=You are not on the team that wrote this feedback'
-
return true
-
end
-
end
-
else
-
reviewer = AssignmentParticipant.find_by_user_id_and_parent_id(session[:user].id, @participant.assignment.id)
-
return true unless current_user_id?(reviewer.user_id)
-
end
-
return false
-
end
-
-
1
def get_body_text(submission)
-
if submission
-
role = "reviewer"
-
item = "submission"
-
else
-
role = "metareviewer"
-
item = "review"
-
end
-
"Hi ##[recipient_name],
-
-
You submitted a score of ##[recipients_grade] for assignment ##[assignment_name] that varied greatly from another "+role+"'s score for the same "+item+".
-
-
The Expertiza system has brought this to my attention."
-
end
-
end
-
1
class ImpersonateController < ApplicationController
-
#auto_complete_for :user, :name
-
-
# auto complete is turned off right now: check the start.html.erb file
-
1
def auto_complete_for_user_name
-
@users = session[:user].get_available_users(params[:user][:name])
-
render :inline => "<%= auto_complete_result @users, 'name' %>", :layout => false
-
end
-
-
1
def start
-
-
end
-
-
1
def impersonate
-
# default error message
-
if params[:user] && params[:user][:name]
-
message = "No user exists with the name '#{params[:user][:name]}'"
-
end
-
-
begin
-
original_user = session[:super_user] || session[:user]
-
-
# Impersonate using form on /impersonate/start
-
if params[:impersonate].nil?
-
user = User.find_by_name(params[:user][:name])
-
if user
-
unless original_user.can_impersonate? user
-
flash[:error] = "You cannot impersonate #{params[:user][:name]}"
-
redirect_back
-
return
-
end
-
-
if session[:super_user] == nil
-
session[:super_user] = session[:user]
-
end
-
AuthController.clear_user_info(session, nil)
-
session[:user] = user
-
else
-
flash[:error] = message
-
redirect_back
-
return
-
end
-
else
-
# Impersonate a new account
-
if params[:impersonate][:name].length > 0
-
user = User.find_by_name(params[:impersonate][:name])
-
if user
-
unless original_user.can_impersonate? user
-
flash[:error] = "You cannot impersonate #{params[:user][:name]}"
-
redirect_back
-
return
-
end
-
-
AuthController.clear_user_info(session, nil)
-
session[:user] = user
-
else
-
flash[:error] = message
-
redirect_back
-
return
-
end
-
# Revert to original account
-
else
-
if session[:super_user] != nil
-
AuthController.clear_user_info(session, nil)
-
session[:user] = session[:super_user]
-
user = session[:user]
-
session[:super_user] = nil
-
else
-
flash[:error] = "No original account was found. Please close your browser and start a new session."
-
redirect_back
-
return
-
end
-
end
-
end
-
# Navigate to user's home location
-
AuthController.set_current_role(user.role_id, session)
-
redirect_to :action => AuthHelper::get_home_action(session[:user]),
-
:controller => AuthHelper::get_home_controller(session[:user])
-
rescue Exception => e
-
flash[:error] = e.message
-
redirect_to :back
-
end
-
-
end
-
end
-
1
class ImportFileController < ApplicationController
-
-
1
def start
-
@id = params[:id]
-
@expected_fields = params[:expected_fields]
-
@model = params[:model]
-
@title = params[:title]
-
end
-
-
1
def import
-
errors = importFile(session,params)
-
err_msg = "The following errors were encountered during import.<br/>Other records may have been added. A second submission will not duplicate these records.<br/><ul>"
-
errors.each{
-
|error|
-
err_msg = err_msg+"<li>"+error+"<br/>"
-
}
-
err_msg = err_msg+"</ul>"
-
if errors.length > 0
-
flash[:error] = err_msg
-
end
-
redirect_to session[:return_to]
-
end
-
-
1
protected
-
1
def importFile(session,params)
-
delimiter = get_delimiter(params)
-
file = params['file']
-
errors = Array.new
-
file.each_line do |line|
-
line.chomp!
-
unless line.empty?
-
row = parse_line(line,delimiter)
-
begin
-
if params[:model] == 'AssignmentTeam' or params[:model] == 'CourseTeam'
-
Object.const_get(params[:model]).import(row,session,params[:id],params[:options])
-
elsif params[:model] == 'SignUpTopic'
-
session[:assignment_id] = params[:id]
-
Object.const_get(params[:model]).import(row,session,params[:id])
-
else
-
Object.const_get(params[:model]).import(row,session,params[:id])
-
end
-
rescue
-
errors << $!
-
end
-
end
-
end
-
return errors
-
end
-
-
1
def get_delimiter(params)
-
delim_type = params[:delim_type]
-
delimiter = case delim_type
-
when "comma" then ","
-
when "space" then " "
-
when "tab" then "\t"
-
when "other" then params[:other_char]
-
end
-
return delimiter
-
end
-
-
1
def parse_line(line, delimiter)
-
if delimiter == ","
-
items = line.split(/,(?=(?:[^\"]*\"[^\"]*\")*(?![^\"]*\"))/)
-
else
-
items = line.split(delimiter)
-
end
-
row = Array.new
-
items.each { | value | row << value.sub("\"","").sub("\"","").strip }
-
return row
-
end
-
end
-
1
class InstitutionsController < ApplicationController
-
1
def index
-
list
-
render :action => 'list'
-
end
-
-
# GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
-
verify :method => :post, :only => [ :destroy, :create, :update ],
-
1
:redirect_to => { :action => :list }
-
-
1
def list
-
@institutions = Institution.paginate(:page => params[:page],:per_page => 10)
-
end
-
-
1
def show
-
@institution = Institution.find(params[:id])
-
end
-
-
1
def new
-
@institution = Institution.new
-
end
-
-
1
def create
-
@institution = Institution.new(params[:institution])
-
if @institution.save
-
flash[:notice] = 'Institution was successfully created.'
-
redirect_to action: :index
-
else
-
render :action => 'new'
-
end
-
end
-
-
1
def edit
-
@institution = Institution.find(params[:id])
-
end
-
-
1
def update
-
@institution = Institution.find(params[:id])
-
if @institution.update_attributes(params[:institution])
-
flash[:notice] = 'Institution was successfully updated.'
-
redirect_to :action => 'show', :id => @institution
-
else
-
render :action => 'edit'
-
end
-
end
-
-
1
def destroy
-
Institution.find(params[:id]).destroy
-
redirect_to :action => 'list'
-
end
-
end
-
1
class InvitationController < ApplicationController
-
1
def new
-
@invitation = Invitation.new
-
end
-
-
1
def create
-
user = User.find_by_name(params[:user][:name].strip)
-
team = AssignmentTeam.find_by_id(params[:team_id])
-
student = AssignmentParticipant.find(params[:student_id])
-
return unless current_user_id?(student.user_id)
-
-
#check if the invited user is valid
-
if !user
-
flash[:notice] = "\"#{params[:user][:name].strip}\" does not exist. Please make sure the name entered is correct."
-
else
-
participant = AssignmentParticipant.find(:first, :conditions => ['user_id =? and parent_id =?', user.id, student.parent_id])
-
if !participant
-
flash[:notice] = "\"#{params[:user][:name].strip}\" is not a participant of this assignment."
-
else
-
team_member = TeamsUser.find(:all, :conditions => ['team_id =? and user_id =?', team.id, user.id])
-
#check if invited user is already in the team
-
if (team_member.size > 0)
-
flash[:notice] = "\"#{user.name}\" is already a member of team."
-
else
-
sent_invitation = Invitation.find(:all, :conditions => ['from_id = ? and to_id = ? and assignment_id = ? and reply_status = "W"', student.user_id, user.id, student.parent_id])
-
#check if the invited user is already invited (i.e. awaiting reply)
-
if sent_invitation.length == 0
-
@invitation = Invitation.new
-
@invitation.to_id = user.id
-
@invitation.from_id = student.user_id
-
@invitation.assignment_id = student.parent_id
-
@invitation.reply_status = 'W'
-
@invitation.save
-
else
-
flash[:notice] = "You have already sent an invitation to \"#{user.name}\"."
-
end
-
end
-
end
-
end
-
redirect_to :controller => 'student_team', :action => 'view', :id=> student.id
-
end
-
-
1
def auto_complete_for_user_name
-
search = params[:user][:name].to_s
-
@users = User.find_by_sql("select * from users where LOWER(name) LIKE '%"+search+"%'") unless search.blank?
-
end
-
-
1
def accept
-
@inv = Invitation.find(params[:inv_id])
-
@inv.reply_status = 'A'
-
@inv.save
-
-
student = Participant.find(params[:student_id])
-
-
#if you are on a team and you accept another invitation, remove your previous entry in the teams_users table.
-
old_entry = TeamsUser.find(:first, :conditions => ['user_id = ? and team_id = ?', student.user_id, params[:team_id]])
-
if old_entry != nil
-
old_entry.destroy
-
end
-
-
#if you are on a team and you accept another invitation and if your old team does not have any members, delete the entry for the team
-
other_members = TeamsUser.find(:all, :conditions => ['team_id = ?', params[:team_id]])
-
if other_members.nil? || other_members.length == 0
-
old_team = AssignmentTeam.find(:first, :conditions => ['id = ?', params[:team_id]])
-
if old_team != nil
-
old_team.destroy
-
end
-
-
#if a signup sheet exists then release all the topics selected by this team into the pool.
-
old_teams_signups = SignedUpUser.find_all_by_creator_id(params[:team_id])
-
if !old_teams_signups.nil?
-
for old_teams_signup in old_teams_signups
-
if old_teams_signup.is_waitlisted == false # i.e., if the old team was occupying a slot, & thus is releasing a slot ...
-
first_waitlisted_signup = SignedUpUser.find_by_topic_id_and_is_waitlisted(old_teams_signup.topic_id, true)
-
if !first_waitlisted_signup.nil?
-
#As this user is going to be allocated a confirmed topic, all of his waitlisted topic signups should be purged
-
first_waitlisted_signup.is_waitlisted = false
-
first_waitlisted_signup.save
-
-
#Also update the participant table. But first_waitlisted_signup.creator_id is the team id
-
#so find one of the users on the team because the update_topic_id function in participant
-
#will take care of updating all the participants on the team
-
user_id = TeamsUser.find(:first, :conditions => {:team_id => first_waitlisted_signup.creator_id}).user_id
-
participant = Participant.find_by_user_id_and_parent_id(user_id,old_team.assignment.id)
-
participant.update_topic_id(old_teams_signup.topic_id)
-
-
SignUpTopic.cancel_all_waitlists(first_waitlisted_signup.creator_id, SignUpTopic.find(old_teams_signup.topic_id)['assignment_id'])
-
end # if !first_waitlisted_signup.nil
-
# Remove the now-empty team from the slot it is occupying.
-
end # if old_teams_signup.is_waitlisted == false
-
old_teams_signup.destroy
-
end
-
end
-
end
-
-
#if you change your team, remove all your invitations that you send to other people
-
old_invs = Invitation.find(:all, :conditions => ['from_id = ? and assignment_id = ?', @inv.to_id, student.parent_id])
-
for old_inv in old_invs
-
old_inv.destroy
-
end
-
-
#create a new team_user entry for the accepted invitation
-
@team_user = TeamsUser.new
-
users_teams = TeamsUser.find(:all, :conditions => ['user_id = ?', @inv.from_id])
-
for team in users_teams
-
current_team = AssignmentTeam.find(:first, :conditions => ['id = ? and parent_id = ?', team.team_id, student.parent_id])
-
if current_team != nil
-
#@team_user.team_id = current_team.id
-
add_member_return= current_team.add_member(User.find(@inv.to_id), @inv.assignment_id)
-
end
-
end
-
-
#also update the user's topic id.
-
if add_member_return # there was room for the member on the team
-
participant = Participant.find_by_user_id_and_parent_id(student.user_id,student.parent_id)
-
participant.update_topic_id(Participant.find_by_user_id_and_parent_id(@inv.from_id,student.parent_id).topic_id)
-
#@team_user.user_id = @inv.to_id
-
#@team_user.save
-
else flash[:error]= "The team already has the maximum number of members."
-
end
-
redirect_to :controller => 'student_team', :action => 'view', :id => student.id
-
end
-
-
1
def decline
-
@inv = Invitation.find(params[:inv_id])
-
@inv.reply_status = 'D'
-
@inv.save
-
student = Participant.find(params[:student_id])
-
redirect_to :controller => 'student_team', :action => 'view', :id => student.id
-
end
-
-
1
def cancel
-
Invitation.find(params[:inv_id]).destroy
-
redirect_to :controller => 'student_team', :action => 'view', :id => params[:student_id]
-
end
-
-
end
-
1
class JoinTeamRequestsController < ApplicationController
-
# GET /join_team_requests
-
# GET /join_team_requests.xml
-
1
def index
-
@join_team_requests = JoinTeamRequest.all
-
-
respond_to do |format|
-
format.html # index.html.erb
-
format.xml { render :xml => @join_team_requests }
-
end
-
end
-
-
# GET /join_team_requests/1
-
# GET /join_team_requests/1.xml
-
1
def show
-
@join_team_request = JoinTeamRequest.find(params[:id])
-
respond_to do |format|
-
format.html # show.html.erb
-
format.xml { render :xml => @join_team_request }
-
end
-
end
-
-
# GET /join_team_requests/new
-
# GET /join_team_requests/new.xml
-
1
def new
-
@join_team_request = JoinTeamRequest.new
-
respond_to do |format|
-
format.html # new.html.erb
-
format.xml { render :xml => @join_team_request }
-
end
-
end
-
-
# GET /join_team_requests/1/edit
-
1
def edit
-
@join_team_request = JoinTeamRequest.find(params[:id])
-
end
-
-
# POST /join_team_requests
-
# POST /join_team_requests.xml
-
#create a new join team request entry for join_team_request table and add it to the table
-
1
def create
-
@join_team_request = JoinTeamRequest.new
-
@join_team_request.comments = params[:comments]
-
@join_team_request.status = 'P'
-
@join_team_request.team_id = params[:team_id]
-
-
participant = Participant.find_by_user_id_and_parent_id(session[:user][:id],params[:assignment_id])
-
@join_team_request.participant_id= participant.id
-
respond_to do |format|
-
if @join_team_request.save
-
format.html { redirect_to(@join_team_request, :notice => 'JoinTeamRequest was successfully created.') }
-
format.xml { render :xml => @join_team_request, :status => :created, :location => @join_team_request }
-
else
-
format.html { render :action => "new" }
-
format.xml { render :xml => @join_team_request.errors, :status => :unprocessable_entity }
-
end
-
end
-
end
-
-
# PUT /join_team_requests/1
-
# PUT /join_team_requests/1.xml
-
#update join team request entry for join_team_request table and add it to the table
-
1
def update
-
@join_team_request = JoinTeamRequest.find(params[:id])
-
respond_to do |format|
-
if @join_team_request.update_attributes(params[:join_team_request])
-
format.html { redirect_to(@join_team_request, :notice => 'JoinTeamRequest was successfully updated.') }
-
format.xml { head :ok }
-
else
-
format.html { render :action => "edit" }
-
format.xml { render :xml => @join_team_request.errors, :status => :unprocessable_entity }
-
end
-
end
-
end
-
-
# DELETE /join_team_requests/1
-
# DELETE /join_team_requests/1.xml
-
-
1
def destroy
-
@join_team_request = JoinTeamRequest.find(params[:id])
-
@join_team_request.destroy
-
-
respond_to do |format|
-
format.html { redirect_to(join_team_requests_url) }
-
format.xml { head :ok }
-
end
-
end
-
#decline request to join the team...
-
1
def decline
-
@join_team_request = JoinTeamRequest.find(params[:id])
-
@join_team_request.status = 'D'
-
@join_team_request.save
-
redirect_to :controller => 'student_team', :action => 'view', :id=>params[:teams_user_id]
-
end
-
end
-
1
class LeaderboardController < ApplicationController
-
-
1
before_filter :authorize
-
-
# Our logic for the overall leaderboard. This method provides the data for
-
# the Top 3 leaderboards and the Personal Achievement leaderboards.
-
1
def index
-
@instructorQuery = LeaderboardHelper.userIsInstructor?(current_user.id)
-
-
if @instructorQuery
-
@courseList = LeaderboardHelper.instructorCourses(current_user.id)
-
else
-
@courseList = LeaderboardHelper.studentInWhichCourses(current_user.id)
-
end
-
-
@csHash= Leaderboard.getParticipantEntriesInCourses(@courseList, @user.id)
-
-
-
@courseAccomp = Hash.new
-
if !@instructorQuery
-
-
@courseAccomp = Leaderboard.extractPersonalAchievements(@csHash, @courseList, @user.id)
-
else
-
@csHash = Leaderboard.sortHash(@csHash)
-
end
-
-
# Setup top 3 leaderboards for easier consumption by view
-
@top3LeaderBoards = Array.new
-
-
@csHash.each_pair{|qtype, courseHash|
-
-
courseHash.each_pair{|course, userGradeArray|
-
courseName = LeaderboardHelper.getCourseName(course)
-
achieveName = LeaderboardHelper.getAchieveName(qtype)
-
-
leaderboardHash = Hash.new
-
leaderboardHash = {:achievement => achieveName,
-
:courseName => courseName,
-
:sortedGrades => userGradeArray}
-
-
@top3LeaderBoards << leaderboardHash
-
}
-
}
-
-
@top3LeaderBoards.sort!{|x,y| x[:courseName] <=> y[:courseName]}
-
# Setup personal achievement leaderboards for easier consumption by view
-
@achievementLeaderBoards = Array.new
-
if !@instructorQuery
-
@courseAccomp.each_pair{ |course, accompHashArray|
-
courseAccompListHash = Hash.new
-
courseAccompListHash[:courseName] = LeaderboardHelper.getCourseName(course)
-
courseAccompListHash[:accompList] = Array.new
-
accompHashArray.each {|accompHash|
-
courseAccompListHash[:accompList] << accompHash
-
}
-
@achievementLeaderBoards << courseAccompListHash
-
}
-
end
-
end
-
end
-
1
class MarkupStylesController < ApplicationController
-
-
# GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
-
verify :method => :post, :only => [ :destroy, :create, :update ],
-
1
:redirect_to => { :action => :list }
-
-
1
def index
-
list
-
render :action => 'list'
-
end
-
-
1
def list
-
@markup_styles = MarkupStyle.paginate(:page => params[:page],:per_page => 10)
-
end
-
-
1
def show
-
@markup_style = MarkupStyle.find(params[:id])
-
end
-
-
1
def new
-
@markup_style = MarkupStyle.new
-
end
-
-
1
def create
-
@markup_style = MarkupStyle.new(params[:markup_style])
-
begin
-
@markup_style.save!
-
flash[:notice] = 'MarkupStyle was successfully created.'
-
redirect_to :action => 'list'
-
rescue
-
render :action => 'new'
-
end
-
end
-
-
1
def edit
-
@markup_style = MarkupStyle.find(params[:id])
-
end
-
-
1
def update
-
@markup_style = MarkupStyle.find(params[:id])
-
if @markup_style.update_attributes(params[:markup_style])
-
redirect_to :action => 'show', :id => @markup_style
-
flash[:notice] = 'MarkupStyle was successfully updated.'
-
else
-
render :action => 'edit'
-
end
-
end
-
-
1
def destroy
-
MarkupStyle.find(params[:id]).destroy
-
redirect_to :action => 'list'
-
end
-
-
end
-
1
require 'menu'
-
-
1
class MenuItemsController < ApplicationController
-
1
def index
-
list
-
render :action => 'list'
-
end
-
-
1
def list
-
# @menu_item_pages, @menu_items = paginate :menu_items, :per_page => 10
-
@menu = Menu.new
-
@items = @menu.get_menu(0)
-
end
-
-
1
def show
-
@menu_item = MenuItem.find(params[:id])
-
end
-
-
1
def new
-
@menu_item = MenuItem.new
-
@menu = Menu.new
-
@items = @menu.get_menu(0)
-
foreign
-
@can_change_parent = false
-
end
-
-
1
def new_for
-
@parent_item = MenuItem.find(params[:id])
-
@menu_item = MenuItem.new
-
@menu_item.parent_id = @parent_item.id
-
foreign
-
@can_change_parent = false
-
render :action => 'new'
-
end
-
-
1
def create
-
# Flash an error if neither an action nor a page has been selected
-
if (params[:menu_item][:controller_action_id] == nil or
-
params[:menu_item][:controller_action_id].length == 0 ) and
-
(params[:menu_item][:content_page_id] == nil or
-
params[:menu_item][:content_page_id].length == 0 )
-
flash[:error] = "You must specify either an Action or a Page!"
-
@menu_item = MenuItem.new(params[:menu_item])
-
@parent_item = MenuItem.find(params[:menu_item][:parent_id])
-
foreign
-
@can_change_parent = false
-
render :action => 'new', :id => params[:id]
-
return
-
end
-
-
@menu_item = MenuItem.new(params[:menu_item])
-
@menu_item.seq = MenuItem.next_seq(@menu_item.parent_id)
-
-
if @menu_item.save
-
flash[:notice] = 'MenuItem was successfully created.'
-
Role.rebuild_cache
-
redirect_to :action => 'list'
-
else
-
foreign
-
render :action => 'new'
-
end
-
end
-
-
1
def edit
-
@menu_item = MenuItem.find(params[:id])
-
foreign
-
@menu = Menu.new
-
@items = @menu.get_menu(0)
-
@can_change_parent = true
-
end
-
-
1
def update
-
# Flash an error if neither an action nor a page has been selected
-
if (params[:menu_item][:controller_action_id] == nil or
-
params[:menu_item][:controller_action_id].length == 0 ) and
-
(params[:menu_item][:content_page_id] == nil or
-
params[:menu_item][:content_page_id].length == 0 )
-
flash[:error] = "You must specify either an Action or a Page!"
-
edit
-
render :action => 'edit'
-
return
-
end
-
-
@menu_item = MenuItem.find(params[:id])
-
# If this has been moved from another parent, need to repack
-
# that parent
-
if params[:parent_id] != @menu_item.parent_id
-
do_repack = true
-
repack_for = @menu_item.parent_id
-
# Put at the end of new parent's list
-
params[:menu_item][:seq] = MenuItem.next_seq(params[:menu_item][:parent_id])
-
else
-
do_repack = false
-
end
-
-
if @menu_item.update_attributes(params[:menu_item])
-
flash[:notice] = 'MenuItem was successfully updated.'
-
if do_repack
-
MenuItem.repack(repack_for)
-
end
-
Role.rebuild_cache
-
# redirect_to :action => 'show', :id => @menu_item
-
redirect_to :action => 'list'
-
else
-
foreign
-
render :action => 'edit'
-
end
-
end
-
-
1
def move_up
-
@menu_item = MenuItem.find(params[:id])
-
@above = @menu_item.above
-
-
if @above
-
@menu_item.update_attribute :seq, (@menu_item.seq - 1)
-
@above.update_attribute :seq, (@above.seq + 1)
-
Role.rebuild_cache
-
end
-
redirect_to :action => 'list'
-
end
-
-
1
def move_down
-
@menu_item = MenuItem.find(params[:id])
-
@below = @menu_item.below
-
-
if @below
-
@menu_item.update_attribute :seq, (@menu_item.seq + 1)
-
@below.update_attribute :seq, (@below.seq - 1)
-
Role.rebuild_cache
-
end
-
redirect_to :action => 'list'
-
end
-
-
1
def destroy
-
@menu_item = MenuItem.find(params[:id])
-
repack_for = @menu_item.parent_id
-
@menu_item.destroy
-
MenuItem.repack(repack_for)
-
Role.rebuild_cache
-
redirect_to :action => 'list'
-
end
-
-
1
def link
-
6
str = params[:name]
-
6
node = session[:menu].select(str)
-
6
if node
-
6
redirect_to node.url
-
else
-
logger.error "(error in menu)"
-
redirect_to "/"
-
end
-
end
-
-
1
def noview
-
@items = MenuItem.items_for_permissions(session[:credentials].permission_ids)
-
end
-
-
-
1
protected
-
-
1
def foreign
-
if self.respond_to?(:id)
-
@parents = MenuItem.where('id != ?', self.id).order(:name)
-
else
-
@parents = MenuItem.order(:name)
-
end
-
-
@parents.unshift MenuItem.new(:id => nil, :name => '(root)')
-
@actions = ControllerAction.order_by_controller_and_action
-
@actions.unshift ControllerAction.new(:id => nil, :name => '(none)')
-
-
@pages = ContentPage.order(:name)
-
@pages.unshift ContentPage.new(:id => nil, :name => '(none)')
-
end
-
-
end
-
1
class ParticipantsController < ApplicationController
-
1
auto_complete_for :user, :name
-
-
1
def list
-
@root_node = Object.const_get(params[:model]+"Node").find_by_node_object_id(params[:id])
-
@parent = Object.const_get(params[:model]).find(params[:id])
-
@participants = @parent.participants
-
@model = params[:model]
-
end
-
-
1
def add
-
curr_object = Object.const_get(params[:model]).find(params[:id])
-
begin
-
curr_object.add_participant(params[:user][:name])
-
rescue
-
url_new_user = url_for :controller => 'users', :action => 'new'
-
flash[:error] = "User #{params[:user][:name]} does not exist. Would you like to <a href = '#{url_new_user}'>create this user?</a>"
-
end
-
redirect_to :action => 'list', :id => curr_object.id, :model => params[:model]
-
end
-
-
1
def delete
-
participant = Participant.find(params[:id])
-
name = participant.user.name
-
parent_id = participant.parent_id
-
begin
-
participant.delete(params[:force])
-
flash[:note] = "#{name} has been removed as a participant."
-
rescue
-
url_yes = url_for :action => 'delete', :id => params[:id], :force => 1
-
url_show = url_for :action => 'delete_display', :id => params[:id], :model => participant.class.to_s.gsub("Participant","")
-
url_no = url_for :action => 'list', :id => parent_id, :model => participant.class.to_s.gsub("Participant","")
-
flash[:error] = "A delete action failed: At least one (1) review mapping or team membership exist for this participant. <br/><a href='#{url_yes}'>Delete this participant</a> | <a href='#{url_show}'>Show me the associated items</a>| <a href='#{url_no}'>Do nothing</a><BR/>"
-
end
-
redirect_to :action => 'list', :id => parent_id, :model => participant.class.to_s.gsub("Participant","")
-
end
-
-
1
def delete_display
-
@participant = Participant.find(params[:id])
-
@model = params[:model]
-
end
-
-
1
def delete_items
-
participant = Participant.find(params[:id])
-
maps = params[:ResponseMap]
-
teamsusers = params[:TeamsUser]
-
-
if !maps.nil?
-
maps.each{
-
|rmap_id|
-
begin
-
ResponseMap.find(rmap_id[0].to_i).delete(true)
-
rescue
-
end
-
}
-
end
-
-
if !teamsusers.nil?
-
teamsusers.each{
-
|tuser_id|
-
begin
-
TeamsUser.find(tuser_id[0].to_i).delete
-
rescue
-
end
-
}
-
end
-
-
redirect_to :action => 'delete', :id => participant.id, :method => :post
-
end
-
-
# Copies existing participants from a course down to an assignment
-
1
def inherit
-
assignment = Assignment.find(params[:id])
-
course = assignment.course
-
if course
-
participants = course.participants
-
if participants.length > 0
-
participants.each{|participant| participant.copy(params[:id])}
-
else
-
flash[:note] = "No participants were found to inherit."
-
end
-
else
-
flash[:error] = "No course was found for this assignment."
-
end
-
redirect_to :controller => 'participants', :action => 'list', :id => assignment.id, :model => 'Assignment'
-
end
-
-
1
def bequeath_all
-
assignment = Assignment.find(params[:id])
-
if assignment.course
-
course = assignment.course
-
assignment.participants.each{
-
|participant|
-
participant.copy(course.id)
-
}
-
flash[:note] = "All participants were successfully copied to \""+course.name+"\""
-
else
-
flash[:error] = "This assignment is not associated with a course."
-
end
-
redirect_to :controller => 'participants', :action => 'list', :id => assignment.id, :model => 'Assignment'
-
end
-
-
# Allow participant to change handle for this assignment
-
# If the participant parameters are available, update the participant
-
# and redirect to the view_actions page
-
1
def change_handle
-
@participant = AssignmentParticipant.find(params[:id])
-
return unless current_user_id?(@participant.user_id)
-
-
if params[:participant] != nil
-
if AssignmentParticipant.find_all_by_parent_id_and_handle(@participant.parent_id, params[:participant][:handle]).length > 0
-
flash[:error] = "<b>#{params[:participant][:handle]}</b> is already in use for this assignment. Please select a different handle."
-
redirect_to :controller => 'participants', :action => 'change_handle', :id => @participant
-
else
-
@participant.update_attributes(params[:participant])
-
redirect_to :controller => 'student_task', :action => 'view', :id => @participant
-
end
-
end
-
end
-
-
1
def delete_assignment_participant
-
contributor = AssignmentParticipant.find(params[:id])
-
name = contributor.name
-
assignment_id = contributor.assignment
-
begin
-
contributor.destroy
-
flash[:note] = "\"#{name}\" is no longer a participant in this assignment."
-
rescue
-
flash[:error] = "\"#{name}\" was not removed. Please ensure that \"#{name}\" is not a reviewer or metareviewer and try again."
-
end
-
redirect_to :controller => 'review_mapping', :action => 'list_mappings', :id => assignment_id
-
end
-
end
-
1
class PasswordRetrievalController < ApplicationController
-
1
def forgotten
-
end
-
-
1
def send_password
-
if params[:user][:email].nil? || params[:user][:email].strip.length == 0
-
flash[:error] = "Please enter an e-mail address"
-
else
-
user = User.find_by_email(params[:user][:email])
-
if user
-
password = user.reset_password # the password is reset
-
MailerHelper::send_mail_to_user(user, "Your Expertiza password has been reset", "send_password", password).deliver
-
flash[:success] = "A new password has been sent to your e-mail address."
-
else
-
flash[:error] = "No account is associated with the address, \""+params[:user][:email]+"\". Please try again."
-
end
-
end
-
redirect_to :action => 'forgotten'
-
end
-
end
-
1
class PermissionsController < ApplicationController
-
1
def index
-
list
-
render :action => 'list'
-
end
-
-
1
def list
-
@permissions = Permission.paginate(:page => params[:page],:per_page => 10)
-
end
-
-
1
def show
-
@permission = Permission.find(params[:id])
-
@pages = ContentPage.find_for_permission(params[:id])
-
@actions = ControllerAction.find_for_permission(params[:id])
-
end
-
-
1
def new
-
@permission = Permission.new
-
end
-
-
1
def create
-
@permission = Permission.new(params[:permission])
-
if @permission.save
-
flash[:notice] = 'Permission was successfully created.'
-
Role.rebuild_cache
-
redirect_to :action => 'list'
-
else
-
render :action => 'new'
-
end
-
end
-
-
1
def edit
-
@permission = Permission.find(params[:id])
-
end
-
-
1
def update
-
@permission = Permission.find(params[:id])
-
if @permission.update_attributes(params[:permission])
-
flash[:notice] = 'Permission was successfully updated.'
-
Role.rebuild_cache
-
redirect_to :action => 'show', :id => @permission
-
else
-
render :action => 'edit'
-
end
-
end
-
-
1
def destroy
-
Permission.find(params[:id]).destroy
-
Role.rebuild_cache
-
redirect_to :action => 'list'
-
end
-
end
-
1
class PgUsersController < UsersController
-
# This method creates an entry in the users table. It is caled from the Add Super-Admin, Add Administrator, Add Instructor, and Add Student functions
-
# The parent field identifies the entity in the users table (e.g., an instructor) that created this entry (e.g., a student).
-
1
def self.create(role, controller, success_action, failure_action)
-
user = User.new(params[:user])
-
user.parent_id = (session[:user]).id
-
user.role_id = role
-
-
if user.save
-
user_type = Role.find(user.role_id).name
-
flash[:notice] = '#{user_type} was successfully created.'
-
redirect_to :controller => controller, :action => success_action
-
else
-
render :controller => controller, :action => failure_action
-
end
-
end
-
-
# user_id - the id (in the users table) of the user to be removed.
-
# user_type - a string representing the type of user that is being removed
-
1
def self.remove_user(user_id, user_type)
-
if user_id then
-
begin
-
user = User.find(user_id)
-
# Change user rights?
-
user.destroy
-
flash[:notice] = "The " + user_type + "<tt>#{user.login}</tt> has been removed."
-
rescue ActiveRecord::RecordNotFound
-
# logging?
-
flash[:notice] = "The " + user_type + "to be removed is not in the database."
-
end
-
end
-
end
-
end
-
1
class ProfileController < ApplicationController
-
1
def edit
-
2
@user = session[:user]
-
2
@assignment_questionnaire = AssignmentQuestionnaire.first :conditions => ['user_id = ? and assignment_id is null and questionnaire_id is null', @user.id]
-
end
-
-
1
def update
-
1
@user = session[:user]
-
-
1
unless params[:assignment_questionnaire].nil? or params[:assignment_questionnaire][:notification_limit].blank?
-
aq = AssignmentQuestionnaire.find(:first, :conditions => ['user_id = ? and assignment_id is null and questionnaire_id is null',@user.id])
-
aq.update_attribute('notification_limit',params[:assignment_questionnaire][:notification_limit])
-
end
-
-
1
if @user.update_attributes(params[:user])
-
1
flash[:success] = 'Profile was successfully updated.'
-
else
-
flash[:error] = 'Profile was not updated.'
-
end
-
-
1
redirect_to controller: :profile, action: :edit
-
end
-
end
-
1
class PublishingController < ApplicationController
-
-
1
def view
-
@user = User.find_by_id(session[:user].id) # Find again, because the user's certificate may have changed since login
-
@participants = AssignmentParticipant.find_all_by_user_id(session[:user].id)
-
end
-
-
1
def set_publish_permission
-
participant = AssignmentParticipant.find(params[:id])
-
return unless current_user_id?(participant.user_id)
-
-
if (params[:allow] == '1')
-
redirect_to :action => 'grant'
-
else
-
participant.update_attribute('permission_granted',params[:allow])
-
redirect_to :action => 'view'
-
end
-
end
-
-
1
def update_publish_permissions
-
if (params[:allow] == '1')
-
redirect_to :action => 'grant'
-
else
-
participants = AssignmentParticipant.find_all_by_user_id(session[:user].id)
-
participants.each do |participant|
-
participant.update_attribute('permission_granted',params[:allow])
-
participant.digital_signature = nil
-
participant.time_stamp = nil
-
participant.save
-
end
-
redirect_to :action => 'view'
-
end
-
end
-
-
# Put up the page where the user can supply their private key and grant publishing rights
-
1
def grant
-
# Lookup the specific assignment (if any) that the user is granting publishing rights to.
-
# This will be nil when the user is granting to all past assignments.
-
if (!params[:id].nil?)
-
@participant = AssignmentParticipant.find(params[:id])
-
end
-
@user = User.find_by_id(session[:user].id) # Find again, because the user's certificate may have changed since login
-
end
-
-
# Grant publishing rights using the private key supplied by the student
-
1
def grant_with_private_key
-
if (params[:id])
-
participants = [ AssignmentParticipant.find(params[:id]) ]
-
else
-
participants = AssignmentParticipant.find_all_by_user_id(session[:user].id)
-
end
-
private_key = params[:private_key]
-
-
begin
-
AssignmentParticipant.grant_publishing_rights(private_key, participants)
-
redirect_to :action => 'view'
-
rescue
-
flash[:notice] = 'Invalid private key.'
-
if (!params[:id].nil?)
-
redirect_to :action => 'grant', :id => participants[0].id
-
else
-
redirect_to :action => 'grant'
-
end
-
end
-
end
-
end
-
1
class QuestionTypesController < ApplicationController
-
# GET /question_types
-
# GET /question_types.xml
-
1
def index
-
@question_types = QuestionType.all
-
-
respond_to do |format|
-
format.html # index.html.erb
-
format.xml { render :xml => @question_types }
-
end
-
end
-
-
# GET /question_types/1
-
# GET /question_types/1.xml
-
1
def show
-
@question_type = QuestionType.find(params[:id])
-
-
respond_to do |format|
-
format.html # show.html.erb
-
format.xml { render :xml => @question_type }
-
end
-
end
-
-
# GET /question_types/new
-
# GET /question_types/new.xml
-
1
def new
-
@question_type = QuestionType.new
-
-
respond_to do |format|
-
format.html # new.html.erb
-
format.xml { render :xml => @question_type }
-
end
-
end
-
-
# GET /question_types/1/edit
-
1
def edit
-
@question_type = QuestionType.find(params[:id])
-
end
-
-
# POST /question_types
-
# POST /question_types.xml
-
1
def create
-
@question_type = QuestionType.new(params[:question_type])
-
-
respond_to do |format|
-
if @question_type.save
-
format.html { redirect_to(@question_type, :notice => 'QuestionType was successfully created.') }
-
format.xml { render :xml => @question_type, :status => :created, :location => @question_type }
-
else
-
format.html { render :action => "new" }
-
format.xml { render :xml => @question_type.errors, :status => :unprocessable_entity }
-
end
-
end
-
end
-
-
# PUT /question_types/1
-
# PUT /question_types/1.xml
-
1
def update
-
@question_type = QuestionType.find(params[:id])
-
-
respond_to do |format|
-
if @question_type.update_attributes(params[:question_type])
-
format.html { redirect_to(@question_type, :notice => 'QuestionType was successfully updated.') }
-
format.xml { head :ok }
-
else
-
format.html { render :action => "edit" }
-
format.xml { render :xml => @question_type.errors, :status => :unprocessable_entity }
-
end
-
end
-
end
-
-
# DELETE /question_types/1
-
# DELETE /question_types/1.xml
-
1
def destroy
-
@question_type = QuestionType.find(params[:id])
-
@question_type.destroy
-
-
respond_to do |format|
-
format.html { redirect_to(question_types_url) }
-
format.xml { head :ok }
-
end
-
end
-
end
-
1
class QuestionnairesController < ApplicationController
-
# Controller for Questionnaire objects
-
# A Questionnaire can be of several types (QuestionnaireType)
-
# Each Questionnaire contains zero or more questions (Question)
-
# Generally a questionnaire is associated with an assignment (Assignment)
-
-
1
before_filter :authorize
-
-
# Create a clone of the given questionnaire, copying all associated
-
# questions. The name and creator are updated.
-
1
def copy
-
orig_questionnaire = Questionnaire.find(params[:id])
-
questions = Question.find_all_by_questionnaire_id(params[:id])
-
@questionnaire = orig_questionnaire.clone
-
@questionnaire.instructor_id = session[:user].instructor_id ## Why was TA-specific code removed here? See Project E713.
-
@questionnaire.name = 'Copy of ' + orig_questionnaire.name
-
-
clone_questionnaire_details(questions)
-
end
-
-
# Remove a given questionnaire
-
1
def delete
-
@questionnaire = Questionnaire.find(params[:id])
-
-
if @questionnaire
-
begin
-
name = @questionnaire.name
-
-
for question in @questionnaire.questions
-
current_q_type = QuestionType.find_by_question_id(question.id)
-
unless current_q_type.nil?
-
current_q_type.delete
-
end
-
end
-
@questionnaire.delete
-
flash[:note] = "Questionnaire <B>#{name}</B> was deleted."
-
rescue
-
flash[:error] = $!
-
end
-
end
-
-
redirect_to :action => 'list', :controller => 'tree_display'
-
end
-
-
1
def view
-
redirect_to action: :show
-
end
-
-
1
def show
-
@questionnaire = Questionnaire.find(params[:id])
-
end
-
-
# Edit a questionnaire
-
1
def edit
-
@questionnaire = Questionnaire.find(params[:id])
-
redirect_to Questionnaire if @questionnaire == nil
-
-
if params['save']
-
@questionnaire.update_attributes(params[:questionnaire])
-
end
-
-
export if params['export']
-
import if params['import']
-
-
if params['view_advice']
-
redirect_to :controller => 'advice', :action => 'edit_advice', :id => params[:questionnaire][:id]
-
end
-
end
-
-
# Define a new questionnaire
-
1
def new
-
1
@questionnaire = Object.const_get(params[:model]).new
-
1
@questionnaire.private = params[:private]
-
1
@questionnaire.min_question_score = Questionnaire::DEFAULT_MIN_QUESTION_SCORE
-
1
@questionnaire.max_question_score = Questionnaire::DEFAULT_MAX_QUESTION_SCORE
-
1
@questionnaire.instruction_loc = Questionnaire::DEFAULT_QUESTIONNAIRE_URL
-
1
@questionnaire.section = "Regular"
-
end
-
-
1
def select_questionnaire_type
-
1
@questionnaire = Object.const_get(params[:questionnaire][:type]).new(params[:questionnaire])
-
1
@questionnaire.private = params[:questionnaire][:private]
-
1
@questionnaire.min_question_score = params[:questionnaire][:min_question_score]
-
1
@questionnaire.max_question_score = params[:questionnaire][:max_question_score]
-
1
@questionnaire.section = params[:questionnaire][:section]
-
1
@questionnaire.id = params[:questionnaire][:id]
-
1
@questionnaire.display_type = params[:questionnaire][:display_type]
-
end
-
-
1
def create
-
1
@questionnaire = Object.const_get(params[:questionnaire][:type]).new(params[:questionnaire])
-
1
if (session[:user]).role.name == "Teaching Assistant"
-
@questionnaire.instructor_id = Ta.get_my_instructor((session[:user]).id)
-
else
-
1
@questionnaire.instructor_id = session[:user].id
-
end
-
1
save
-
1
redirect_to :controller => 'tree_display', :action => 'list'
-
end
-
-
1
def update
-
@questionnaire = Questionnaire.find(params[:id])
-
if current_user.role == Role.ta
-
@questionnaire.instructor_id = Ta.get_my_instructor(current_user.id)
-
else
-
@questionnaire.instructor_id = current_user.id
-
end
-
-
if @questionnaire.update_attributes(params[:questionnaire])
-
redirect_to :controller => 'tree_display', :action => 'list'
-
else
-
render 'edit'
-
end
-
end
-
-
1
def edit_advice ##Code used to be in this class, was removed. I have not checked the other class.
-
redirect_to :controller => 'advice', :action => 'edit_advice'
-
end
-
-
1
def save_advice
-
begin
-
for advice_key in params[:advice].keys
-
QuestionAdvice.update(advice_key, params[:advice][advice_key])
-
end
-
flash[:notice] = "The questionnaire's question advice was successfully saved"
-
#redirect_to :action => 'list'
-
redirect_to :controller => 'advice', :action => 'save_advice'
-
end ##Rescue clause was removed; why?
-
end
-
-
# Toggle the access permission for this assignment from public to private, or vice versa
-
1
def toggle_access
-
questionnaire = Questionnaire.find(params[:id])
-
questionnaire.private = !questionnaire.private
-
questionnaire.save
-
-
redirect_to :controller => 'tree_display', :action => 'list'
-
end
-
-
1
private
-
-
#save questionnaire object after create or edit
-
1
def save
-
1
begin
-
1
@questionnaire.save!
-
1
save_questions @questionnaire.id if @questionnaire.id != nil and @questionnaire.id > 0
-
1
pFolder = TreeFolder.find_by_name(@questionnaire.display_type)
-
1
parent = FolderNode.find_by_node_object_id(pFolder.id)
-
1
if QuestionnaireNode.find_by_parent_id_and_node_object_id(parent.id,@questionnaire.id) == nil
-
1
QuestionnaireNode.create(:parent_id => parent.id, :node_object_id => @questionnaire.id)
-
end
-
rescue
-
flash[:error] = $!
-
end
-
end
-
-
#save parameters for new questions
-
1
def save_new_question_parameters(qid, q_num)
-
q = QuestionType.new
-
q.q_type = params[:question_type][q_num][:type]
-
q.parameters = params[:question_type][q_num][:parameters]
-
q.question_id = qid
-
q.save
-
end
-
-
# save questions that have been added to a questionnaire
-
1
def save_new_questions(questionnaire_id)
-
1
if params[:new_question]
-
# The new_question array contains all the new questions
-
# that should be saved to the database
-
for question_key in params[:new_question].keys
-
q = Question.new(params[:new_question][question_key])
-
q.questionnaire_id = questionnaire_id
-
if q.true_false == ''
-
q.true_false = false
-
end
-
unless q.txt.strip.empty?
-
q.save
-
questionnaire = Questionnaire.find_by_id(questionnaire_id)
-
if questionnaire.section == "Custom"
-
for i in (questionnaire.min_question_score .. questionnaire.max_question_score)
-
a = QuestionAdvice.new(:score => i, :advice => nil)
-
a.question_id = q.id
-
a.save
-
end
-
save_new_question_parameters(q.id, question_key)
-
end
-
end
-
end
-
end
-
end
-
-
# delete questions from a questionnaire
-
# @param [Object] questionnaire_id
-
1
def delete_questions(questionnaire_id)
-
# Deletes any questions that, as a result of the edit, are no longer in the questionnaire
-
1
questions = Question.find(:all, :conditions => "questionnaire_id = " + questionnaire_id.to_s)
-
1
for question in questions
-
should_delete = true
-
if params[:question] != nil
-
for question_key in params[:question].keys
-
if question_key.to_s === question.id.to_s
-
should_delete = false
-
end
-
end
-
end
-
if should_delete
-
for advice in question.question_advices
-
advice.destroy
-
end
-
if Questionnaire.find_by_id(questionnaire_id).section == "Custom"
-
question_type = QuestionType.find_by_question_id(question.id)
-
question_type.destroy
-
end
-
question.destroy
-
end
-
end
-
end
-
-
# @param [Object] question_type_key
-
1
def update_question_type (question_type_key)
-
this_q = QuestionType.find(question_type_key)
-
this_q.parameters = params[:q][question_type_key][:parameters]
-
-
if params[:q][question_type_key][:q_type] == "0"
-
this_q.q_type = Question::GRADING_TYPES_CUSTOM[0][0]
-
elsif params[:q][question_type_key][:q_type] == "1"
-
this_q.q_type = Question::GRADING_TYPES_CUSTOM[1][0]
-
elsif params[:q][question_type_key][:q_type] == "2"
-
this_q.q_type = Question::GRADING_TYPES_CUSTOM[2][0]
-
elsif params[:q][question_type_key][:q_type] == "3"
-
this_q.q_type = Question::GRADING_TYPES_CUSTOM[3][0]
-
elsif params[:q][question_type_key][:q_type] == "4"
-
this_q.q_type = Question::GRADING_TYPES_CUSTOM[4][0]
-
else
-
this_q.q_type = Question::GRADING_TYPES_CUSTOM[5][0]
-
end
-
-
unless this_q.nil?
-
this_q.save
-
end
-
end
-
-
# Handles questions whose wording changed as a result of the edit
-
# @param [Object] questionnaire_id
-
1
def save_questions(questionnaire_id)
-
1
delete_questions questionnaire_id
-
1
save_new_questions questionnaire_id
-
-
1
if params[:question]
-
for question_key in params[:question].keys
-
begin
-
if params[:question][question_key][:txt].strip.empty?
-
# question text is empty, delete the question
-
if Questionnaire.find_by_id(questionnaire_id).section == "Custom"
-
QuestionType.find_by_question_id(question_key).delete
-
end
-
Question.delete(question_key)
-
else
-
# Update existing question.
-
Question.update(question_key, params[:question][question_key])
-
end
-
rescue ActiveRecord::RecordNotFound
-
# ignored
-
end
-
end
-
if Questionnaire.find_by_id(questionnaire_id).section == "Custom"
-
for question_type_key in params[:q].keys
-
update_question_type(question_type_key)
-
end
-
end
-
end
-
end
-
-
1
private
-
-
# FIXME: These private methods belong in the Questionnaire model
-
-
1
def export
-
@questionnaire = Questionnaire.find(params[:id])
-
-
csv_data = QuestionnaireHelper::create_questionnaire_csv @questionnaire, session[:user].name
-
-
send_data csv_data,
-
:type => 'text/csv; charset=iso-8859-1; header=present',
-
:disposition => "attachment; filename=questionnaires.csv"
-
end
-
-
1
def import
-
@questionnaire = Questionnaire.find(params[:id])
-
-
file = params['csv']
-
-
@questionnaire.questions << QuestionnaireHelper::get_questions_from_csv(@questionnaire, file)
-
end
-
-
# clones the contents of a questionnaire, including the questions and associated advice
-
1
def clone_questionnaire_details(questions)
-
begin
-
@questionnaire.save!
-
@questionnaire.update_attribute('created_at', Time.now)
-
-
questions.each do |question|
-
newquestion = question.clone
-
newquestion.questionnaire_id = @questionnaire.id
-
newquestion.save
-
-
advice = QuestionAdvice.find_by_question_id(question.id)
-
unless advice.nil?
-
newadvice = advice.clone
-
newadvice.question_id = newquestion.id
-
newadvice.save
-
end
-
-
if @questionnaire.section == "Custom"
-
old_question_type = QuestionType.find_by_question_id(question.id)
-
unless old_question_type.nil?
-
new_question_type = old_question_type.clone
-
new_question_type.question_id = newquestion.id
-
new_question_type.save
-
end
-
end
-
end
-
-
pFolder = TreeFolder.find_by_name(@questionnaire.display_type)
-
parent = FolderNode.find_by_node_object_id(pFolder.id)
-
if QuestionnaireNode.find_by_parent_id_and_node_object_id(parent.id, @questionnaire.id) == nil
-
QuestionnaireNode.create(:parent_id => parent.id, :node_object_id => @questionnaire.id)
-
end
-
redirect_to :controller => 'questionnaire', :action => 'view', :id => @questionnaire.id
-
rescue
-
flash[:error] = 'The questionnaire was not able to be copied. Please check the original course for missing information.'+$!
-
redirect_to :action => 'list', :controller => 'tree_display'
-
end
-
end
-
end
-
1
class QuestionsController < ApplicationController
-
-
# A question is a single entry within a questionnaire
-
# Questions provide a way of scoring an object
-
# based on either a numeric value or a true/false
-
# state.
-
-
# Default action, same as list
-
1
def index
-
list
-
render :action => 'list'
-
end
-
-
# GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
-
verify :method => :post, :only => [ :destroy, :create, :update ],
-
1
:redirect_to => { :action => :list }
-
-
-
# List all questions in paginated view
-
1
def list
-
@questions = Question.paginate(:page => params[:page],:per_page => 10)
-
end
-
-
# List questions for this user
-
# ?? Need clarification of what this task
-
# actually does.
-
1
def listuser
-
@question = Array.new
-
@i = 0
-
@sign_qts = SignupQuestion.find(:all,
-
:conditions => 'signup_id = '+@params[:id].to_s,
-
:order => 'id')
-
-
end
-
-
# ?? Unknown as of 2/1/2009
-
# Need further investigation
-
1
def SignupSheet
-
@questions = Question.paginate(:page => params[:page],:per_page => 10)
-
end
-
-
# Display a given question
-
1
def show
-
@question = Question.find(params[:id])
-
end
-
-
# Provide the user with the ability to define
-
# a new question
-
1
def new
-
@question = Question.new
-
end
-
-
# Save a question created by the user
-
# follows from new
-
1
def create
-
@question = Question.new(params[:question])
-
if @question.save
-
flash[:notice] = 'Question was successfully created.'
-
redirect_to :action => 'list'
-
else
-
render :action => 'new'
-
end
-
end
-
-
# edit an existing question
-
1
def edit
-
@question = Question.find(params[:id])
-
end
-
-
# save the update to an existing question
-
# follows from edit
-
1
def update
-
@question = Question.find(params[:id])
-
if @question.update_attributes(params[:question])
-
flash[:notice] = 'Question was successfully updated.'
-
redirect_to :action => 'show', :id => @question
-
else
-
render :action => 'edit'
-
end
-
end
-
-
# Remove question from database and
-
# return to list
-
1
def destroy
-
Question.find(params[:id]).destroy
-
redirect_to :action => 'list'
-
end
-
end
-
1
class ReportsController < ApplicationController
-
1
def view
-
@assignment_id=14;
-
-
@due_dates = DueDate.find(:all, :conditions => ["assignment_id = ?",@assignment_id])
-
@late_policy = Assignment.find(@assignment_id).late_policy
-
# Find the next due date (after the current date/time), and then find the type of deadline it is.
-
@very_last_due_date = DueDate.find(:all,:order => "due_at DESC", :limit =>1)
-
@next_due_date = @very_last_due_date[0]
-
for due_date in @due_dates
-
if due_date.due_at > Time.now
-
if due_date.due_at < @next_due_date.due_at
-
@next_due_date = due_date
-
end
-
end
-
end
-
-
-
@review_phase = @next_due_date.deadline_type_id;
-
-
-
-
end
-
end
-
1
class ResponseController < ApplicationController
-
1
helper :wiki
-
1
helper :submitted_content
-
1
helper :file
-
-
1
def delete
-
@response = Response.find(params[:id])
-
return if redirect_when_disallowed(@response)
-
-
map_id = @response.map.id
-
@response.delete
-
redirect_to :action => 'redirection', :id => map_id, :return => params[:return], :msg => "The response was deleted."
-
end
-
-
#Determining the current phase and check if a review is already existing for this stage.
-
#If so, edit that version otherwise create a new version.
-
-
1
def rereview
-
@map=ResponseMap.find(params[:id])
-
get_content
-
array_not_empty=0
-
@review_scores=Array.new
-
@prev=Response.all
-
#get all versions and find the latest version
-
for element in @prev
-
if(element.map_id==@map.id)
-
array_not_empty=1
-
@review_scores << element
-
end
-
end
-
-
#sort all the available versions in descending order.
-
if array_not_empty==1
-
@sorted=@review_scores.sort { |m1,m2|(m1.version_num and m2.version_num) ? m2.version_num <=> m1.version_num : (m1.version_num ? -1 : 1)}
-
@largest_version_num=@sorted[0]
-
@latest_phase=@largest_version_num.created_at
-
due_dates = DueDate.find(:all, :conditions => ["assignment_id = ?", @assignment.id])
-
@sorted_deadlines=Array.new
-
@sorted_deadlines=due_dates.sort {|m1,m2|(m1.due_at and m2.due_at) ? m1.due_at <=> m2.due_at : (m1.due_at ? -1 : 1)}
-
current_time=Time.new.getutc
-
#get the highest version numbered review
-
next_due_date=@sorted_deadlines[0]
-
-
#check in which phase the latest review was done.
-
for deadline_version in @sorted_deadlines
-
if(@largest_version_num.created_at < deadline_version.due_at )
-
break
-
end
-
end
-
for deadline_time in @sorted_deadlines
-
if(current_time < deadline_time.due_at)
-
break
-
end
-
end
-
end
-
-
#check if the latest review is done in the current phase.
-
#if latest review is in current phase then edit the latest one.
-
#else create a new version and update it.
-
-
# editing the latest review
-
if(deadline_version.due_at== deadline_time.due_at)
-
#send it to edit here
-
@header = "Edit"
-
@next_action = "update"
-
@return = params[:return]
-
@response = Response.find_by_map_id_and_version_num(params[:id],@largest_version_num.version_num)
-
return if redirect_when_disallowed(@response)
-
@modified_object = @response.id
-
@map = @response.map
-
get_content
-
@review_scores = Array.new
-
@questions.each{
-
| question |
-
@review_scores << Score.find_by_response_id_and_question_id(@response.id, question.id)
-
}
-
#**********************
-
# Check whether this is Jen's assgt. & if so, use her rubric
-
if (@assignment.instructor_id == User.find_by_name("jace_smith").id) && @title == "Review"
-
if @assignment.id < 469
-
@next_action = "custom_update"
-
render :action => 'custom_response'
-
else
-
@next_action = "custom_update"
-
render :action => 'custom_response_2011'
-
end
-
else
-
# end of special code (except for the end below, to match the if above)
-
#**********************
-
-
render :action => 'response'
-
-
end
-
# render :action => 'edit'
-
else
-
#else create a new version and update it.
-
-
@header = "New"
-
@next_action = "create"
-
@feedback = params[:feedback]
-
@map = ResponseMap.find(params[:id])
-
@return = params[:return]
-
@modified_object = @map.id
-
get_content
-
#**********************
-
# Check whether this is Jen's assgt. & if so, use her rubric
-
if (@assignment.instructor_id == User.find_by_name("jace_smith").id) && @title == "Review"
-
if @assignment.id < 469
-
@next_action = "custom_create"
-
render :action => 'custom_response'
-
else
-
@next_action = "custom_create"
-
render :action => 'custom_response_2011'
-
end
-
else
-
# end of special code (except for the end below, to match the if above)
-
#**********************
-
render :action => 'response'
-
end
-
-
end
-
end
-
-
1
def edit
-
@header = "Edit"
-
@next_action = "update"
-
@return = params[:return]
-
@response = Response.find(params[:id])
-
return if redirect_when_disallowed(@response)
-
-
@map = @response.map
-
array_not_empty=0
-
@review_scores=Array.new
-
@prev=Response.all
-
for element in @prev
-
if(element.map_id==@map.id)
-
array_not_empty=1
-
@review_scores << element
-
end
-
end
-
if array_not_empty==1
-
@sorted=@review_scores.sort { |m1,m2|(m1.version_num and m2.version_num) ? m2.version_num <=> m1.version_num : (m1.version_num ? -1 : 1)}
-
@largest_version_num=@sorted[0]
-
end
-
@response = Response.find_by_map_id_and_version_num(@map.id,@largest_version_num.version_num)
-
@modified_object = @response.id
-
get_content
-
@review_scores = Array.new
-
@question_type = Array.new
-
@questions.each{
-
| question |
-
@review_scores << Score.find_by_response_id_and_question_id(@response.id, question.id)
-
@question_type << QuestionType.find_by_question_id(question.id)
-
}
-
# Check whether this is a custom rubric
-
if @map.questionnaire.section.eql? "Custom"
-
@next_action = "custom_update"
-
render :action => 'custom_response'
-
else
-
# end of special code (except for the end below, to match the if above)
-
#**********************
-
render :action => 'response'
-
end
-
end
-
-
1
def update
-
@response = Response.find(params[:id])
-
return if redirect_when_disallowed(@response)
-
@myid = @response.id
-
msg = ""
-
begin
-
@myid = @response.id
-
@map = @response.map
-
@response.update_attribute('additional_comment',params[:review][:comments])
-
-
@questionnaire = @map.questionnaire
-
questions = @questionnaire.questions
-
-
params[:responses].each_pair do |k,v|
-
-
score = Score.find_by_response_id_and_question_id(@response.id, questions[k.to_i].id)
-
if(score == nil)
-
score = Score.create(:response_id => @response.id, :question_id => questions[k.to_i].id, :score => v[:score], :comments => v[:comment])
-
end
-
score.update_attribute('score',v[:score])
-
score.update_attribute('comments',v[:comment])
-
end
-
rescue
-
msg = "Your response was not saved. Cause: "+ $!
-
end
-
-
begin
-
ResponseHelper.compare_scores(@response, @questionnaire)
-
ScoreCache.update_cache(@response.id)
-
-
msg = "Your response was successfully saved."
-
rescue
-
msg = "An error occurred while saving the response: "+$!
-
end
-
redirect_to :controller => 'response', :action => 'saving', :id => @map.id, :return => params[:return], :msg => msg, :save_options => params[:save_options]
-
end
-
-
1
def custom_update
-
@response = Response.find(params[:id])
-
@myid = @response.id
-
msg = ""
-
begin
-
@myid = @response.id
-
@map = @response.map
-
@response.update_attribute('additional_comment',"")
-
-
@questionnaire = @map.questionnaire
-
questions = @questionnaire.questions
-
-
for i in 0..questions.size-1
-
score = Score.find_by_response_id_and_question_id(@response.id, questions[i.to_i].id)
-
score.update_attribute('comments',params[:custom_response][i.to_s])
-
end
-
rescue
-
msg = "#{@map.get_title} was not saved."
-
end
-
-
msg = "#{@map.get_title} was successfully saved."
-
redirect_to :controller => 'response', :action => 'saving', :id => @map.id, :return => params[:return], :msg => msg, :save_options => params[:save_options]
-
end
-
-
1
def new_feedback
-
review = Response.find(params[:id])
-
if review
-
reviewer = AssignmentParticipant.find_by_user_id_and_parent_id(session[:user].id, review.map.assignment.id)
-
map = FeedbackResponseMap.find_by_reviewed_object_id_and_reviewer_id(review.id, reviewer.id)
-
if map.nil?
-
map = FeedbackResponseMap.create(:reviewed_object_id => review.id, :reviewer_id => reviewer.id, :reviewee_id => review.map.reviewer.id)
-
end
-
redirect_to :action => 'new', :id => map.id, :return => "feedback"
-
else
-
redirect_to :back
-
end
-
end
-
-
1
def view
-
@response = Response.find(params[:id])
-
return if redirect_when_disallowed(@response)
-
@map = @response.map
-
get_content
-
@review_scores = Array.new
-
@question_type = Array.new
-
@questions.each{
-
| question |
-
@review_scores << Score.find_by_response_id_and_question_id(@response.id, question.id)
-
@question_type << QuestionType.find_by_question_id(question.id)
-
}
-
end
-
-
1
def new
-
@header = "New"
-
@next_action = "create"
-
@feedback = params[:feedback]
-
@map = ResponseMap.find(params[:id])
-
@return = params[:return]
-
@modified_object = @map.id
-
get_content
-
-
# Check whether this is a custom rubric
-
if @map.questionnaire.section.eql? "Custom"
-
@question_type = Array.new
-
@questions.each{
-
| question |
-
@question_type << QuestionType.find_by_question_id(question.id)
-
}
-
if !@map.contributor.nil?
-
if @map.assignment.team_assignment?
-
team_member = TeamsUser.find_by_team_id(@map.contributor).user_id
-
@topic_id = Participant.find_by_parent_id_and_user_id(@map.assignment.id,team_member).topic_id
-
else
-
@topic_id = Participant.find(@map.contributor).topic_id
-
end
-
end
-
if !@topic_id.nil?
-
@signedUpTopic = SignUpTopic.find(@topic_id).topic_name
-
end
-
@next_action = "custom_create"
-
render :action => 'custom_response'
-
else
-
render :action => 'response'
-
end
-
end
-
-
1
def create
-
@map = ResponseMap.find(params[:id])
-
@res = 0
-
msg = ""
-
error_msg = ""
-
-
begin
-
-
#get all previous versions of responses for the response map.
-
array_not_empty=0
-
@review_scores=Array.new
-
@prev=Response.all
-
for element in @prev
-
if(element.map_id==@map.id)
-
array_not_empty=1
-
@review_scores << element
-
end
-
end
-
-
#if previous responses exist increment the version number.
-
if array_not_empty==1
-
@sorted=@review_scores.sort { |m1,m2|(m1.version_num and m2.version_num) ? m2.version_num <=> m1.version_num : (m1.version_num ? -1 : 1)}
-
@largest_version_num=@sorted[0]
-
if(@largest_version_num.version_num==nil)
-
@version=1
-
else
-
@version=@largest_version_num.version_num+1
-
end
-
-
#if no previous version is available then initial version number is 1
-
else
-
@version=1
-
end
-
@response = Response.create(:map_id => @map.id, :additional_comment => params[:review][:comments],:version_num=>@version)
-
@res = @response.id
-
@questionnaire = @map.questionnaire
-
questions = @questionnaire.questions
-
params[:responses].each_pair do |k,v|
-
score = Score.create(:response_id => @response.id, :question_id => questions[k.to_i].id, :score => v[:score], :comments => v[:comment])
-
end
-
rescue
-
error_msg = "Your response was not saved. Cause: " + $!
-
end
-
-
begin
-
ResponseHelper.compare_scores(@response, @questionnaire)
-
ScoreCache.update_cache(@res)
-
@map.save
-
msg = "Your response was successfully saved."
-
rescue
-
@response.delete
-
error_msg = "Your response was not saved. Cause: " + $!
-
end
-
-
redirect_to :controller => 'response', :action => 'saving', :id => @map.id, :return => params[:return], :msg => msg, :error_msg => error_msg, :save_options => params[:save_options]
-
end
-
-
1
def custom_create
-
@map = ResponseMap.find(params[:id])
-
@response = Response.create(:map_id => @map.id, :additional_comment => "")
-
@res = @response.id
-
@questionnaire = @map.questionnaire
-
questions = @questionnaire.questions
-
for i in 0..questions.size-1
-
# Local variable score is unused; can it be removed?
-
score = Score.create(:response_id => @response.id, :question_id => questions[i].id, :score => @questionnaire.max_question_score, :comments => params[:custom_response][i.to_s])
-
end
-
msg = "#{@map.get_title} was successfully saved."
-
-
saving
-
end
-
-
1
def saving
-
@map = ResponseMap.find(params[:id])
-
@return = params[:return]
-
@map.notification_accepted = false
-
@map.save
-
#@map.assignment.id == 561 or @map.assignment.id == 559 or
-
if(@map.assignment.id == 562) #Making the automated metareview feature available for one 'ethical analysis 6' assignment only.
-
#puts("*** saving for me:: #{params[:id]} and metareview selection :save_options - #{params["save_options"]}")
-
if(params["save_options"].nil? or params["save_options"].empty?)#default it to with metareviews
-
params["save_options"] = "WithMeta"
-
end
-
#calling the automated metareviewer controller, which calls its corresponding model/view
-
if(params[:save_options] == "WithMeta")
-
# puts "WithMeta"
-
redirect_to :controller => 'automated_metareviews', :action => 'list', :id => @map.id
-
elsif(params[:save_options] == "EmailMeta")
-
redirect_to :action => 'redirection', :id => @map.id, :return => params[:return], :msg => params[:msg], :error_msg => params[:error_msg]
-
# calculate the metareview metrics
-
@automated_metareview = AutomatedMetareview.new
-
#pass in the response id as a parameter
-
@response = Response.find_by_map_id(params[:id])
-
@automated_metareview.calculate_metareview_metrics(@response, params[:id])
-
#send email to the reviewer with the metareview details
-
@automated_metareview.send_metareview_metrics_email(@response, params[:id])
-
elsif(params[:save_options] == "WithoutMeta")
-
# puts "WithoutMeta"
-
redirect_to :action => 'redirection', :id => @map.id, :return => params[:return], :msg => params[:msg], :error_msg => params[:error_msg]
-
end
-
else
-
redirect_to :action => 'redirection', :id => @map.id, :return => params[:return], :msg => params[:msg], :error_msg => params[:error_msg]
-
end
-
end
-
-
1
def redirection
-
flash[:error] = params[:error_msg] unless params[:error_msg] and params[:error_msg].empty?
-
flash[:note] = params[:msg] unless params[:msg] and params[:msg].empty?
-
-
@map = ResponseMap.find(params[:id])
-
if params[:return] == "feedback"
-
redirect_to :controller => 'grades', :action => 'view_my_scores', :id => @map.reviewer.id
-
elsif params[:return] == "teammate"
-
redirect_to :controller => 'student_team', :action => 'view', :id => @map.reviewer.id
-
elsif params[:return] == "instructor"
-
redirect_to :controller => 'grades', :action => 'view', :id => @map.assignment.id
-
else
-
redirect_to :controller => 'student_review', :action => 'list', :id => @map.reviewer.id
-
end
-
end
-
-
1
private
-
-
1
def get_content
-
@title = @map.get_title
-
@assignment = @map.assignment
-
@participant = @map.reviewer
-
@contributor = @map.contributor
-
@questionnaire = @map.questionnaire
-
@questions = @questionnaire.questions
-
@min = @questionnaire.min_question_score
-
@max = @questionnaire.max_question_score
-
end
-
-
1
def redirect_when_disallowed(response)
-
# For author feedback, participants need to be able to read feedback submitted by other teammates.
-
# If response is anything but author feedback, only the person who wrote feedback should be able to see it.
-
if response.map.read_attribute(:type) == 'FeedbackResponseMap' && response.map.assignment.team_assignment?
-
team = response.map.reviewer.team
-
unless team.has_user session[:user]
-
redirect_to '/denied?reason=You are not on the team that wrote this feedback'
-
else
-
return false
-
end
-
response.map.read_attribute(:type)
-
end
-
-
!current_user_id?(response.map.reviewer.user_id)
-
end
-
end
-
1
class ReviewFilesController < ApplicationController
-
1
rescue_from Exception, :with => :render_error_page
-
1
helper :diff
-
-
# This method accepts the review_file from the view-form and calculates/creates
-
# appropriate directories to store the file. The following two parameters need
-
# to be passed in from the view:
-
# params[:participant_id], params[:uploaded_review_file]
-
1
def submit_review_file
-
participant = AssignmentParticipant.find(params[:participant_id])
-
return unless current_user_id?(participant.user_id)
-
-
file = params[:uploaded_review_file]
-
new_version_number = ReviewFile.get_max_version_num(participant) + 1
-
-
# Calculate the directory for unzipping files
-
participant.set_student_directory_num
-
version_dir = ReviewFilesHelper::get_version_directory(participant,
-
new_version_number)
-
FileUtils.mkdir_p(version_dir) unless File.exists? version_dir
-
-
filename_only = ReviewFilesHelper::get_safe_filename(
-
file.original_filename.to_s)
-
full_filename = version_dir + filename_only
-
-
# Check if file is a zip file. If not, display flash message.
-
if ReviewFilesHelper::get_file_type(filename_only) != "zip"
-
flash[:error] = "Uploaded file is not a zip file. Please upload zip files" +
-
" only."
-
redirect_to :action => 'show_all_submitted_files',
-
:participant_id => participant.id and return
-
end
-
-
-
# Copy zip file into version_dir
-
File.open(full_filename, "wb") { |f| f.write(file.read) }
-
-
# Unzip submission
-
SubmittedContentHelper::unzip_file(full_filename, version_dir, true)
-
-
# For all files in the version_dir, add entries in the review_file table
-
participant.get_files(version_dir).each do |each_file|
-
@review_file = ReviewFile.new
-
@review_file.filepath = each_file.to_s
-
@review_file.version_number = new_version_number
-
@review_file.author_participant_id = participant.id
-
@success = @review_file.save ? true : false
-
end
-
-
respond_to do |format|
-
if @success
-
format.html { redirect_to :action => 'show_all_submitted_files',
-
:participant_id => participant.id and return}
-
format.xml { render :xml => @review_file, :status => :created,
-
:location => @review_file and return}
-
else
-
flash[:error] = "Code Review File was <b>not</b> successfully" +
-
"uploaded. Please Re-Submit."
-
format.html { redirect_to :action => 'show_all_submitted_files',
-
:participant_id => participant.id and return}
-
format.xml { render :xml => @review_file.errors,
-
:status => :unprocessable_entity and return}
-
end
-
end
-
-
end
-
-
-
# This method computes the list of all files submitted by the participant along
-
# with all the versions the files are present in. This method needs the following
-
# two parameters:
-
# params[:participant_id], Needs params[:stage]
-
1
def show_all_submitted_files
-
@participant = AssignmentParticipant.find(params[:participant_id])
-
@stage = params[:stage]
-
-
# Find all files over all versions submitted by the team
-
all_review_files = []
-
if @participant.assignment.team_assignment?
-
@participant.team.get_participants.each { |member|
-
all_review_files += ReviewFile.find_all_by_author_participant_id(member.id)
-
}
-
else
-
all_review_files = ReviewFile.find_all_by_author_participant_id(@participant.id)
-
end
-
-
# For each file in the above list find out the various versions in which it occurs
-
@file_version_map = Hash.new
-
all_review_files.each do |each_file|
-
@file_version_map[File.basename(each_file.filepath)] = Array.new unless
-
@file_version_map[File.basename(each_file.filepath)]
-
@file_version_map[File.basename(each_file.filepath)] << each_file.version_number
-
end
-
-
code_review_dir = ReviewFilesHelper::get_code_review_file_dir(@participant)
-
-
# For each file in the above map create a new map, to store the
-
# filename -> review_file_id mapping.
-
@file_id_map = Hash.new
-
@latest_version_number = 0
-
@file_version_map.each do |base_filename, versions|
-
review_file = ReviewFile.get_file(code_review_dir, versions.sort.last,
-
base_filename)
-
@file_id_map[base_filename] = review_file ? review_file.id : nil
-
@file_version_map[base_filename] = versions.sort
-
@latest_version_number = (@file_version_map[base_filename][-1] >
-
@latest_version_number) ? @file_version_map[base_filename][-1] :
-
@latest_version_number
-
end
-
-
end
-
-
-
-
# This method is used to generate the view where the particular code file is
-
# viewed 'individually' (not diff).
-
# params[:review_file_id] - Id of the review_file whose source is to be shown
-
# params[:participant_id]
-
# params[:versions] an array (in asc order) of all versions of the review file
-
# contained in params[:review_file_id]
-
1
def show_code_file
-
@participant = AssignmentParticipant.find(params[:participant_id])
-
@current_review_file = ReviewFile.find(params[:review_file_id])
-
-
@version_fileId_map = Hash.new
-
params[:versions].each do |each_version|
-
this_file = ReviewFile.get_file(
-
ReviewFilesHelper::get_code_review_file_dir(@participant),
-
each_version, File.basename(@current_review_file.filepath))
-
@version_fileId_map[each_version] = this_file ? this_file.id : nil
-
end
-
-
file_contents = File.open(@current_review_file.filepath).readlines
-
-
offset_array = [0]
-
for i in (1..file_contents.length)
-
offset_array << (offset_array[i-1] + file_contents[i-1].size-1)
-
end
-
-
@shareObj = Hash.new()
-
@shareObj['linearray2'] = file_contents
-
@shareObj['offsetarray2'] = offset_array
-
-
newer_version_comments = ReviewComment.find_all_by_review_file_id(
-
@current_review_file.id)
-
-
@highlight_cell_right_file = Hash.new
-
newer_version_comments.each do |each_comment|
-
table_row_num = offset_array.index(each_comment.file_offset)
-
table_row_num = offset_array.length + 1 unless table_row_num
-
-
# Increment table_row_num until a non "" string is encountered in @first_line_num
-
while ( (file_contents[table_row_num].nil? or
-
file_contents[table_row_num].blank?) and
-
table_row_num < file_contents.length)
-
table_row_num += 1
-
end
-
-
@highlight_cell_right_file[table_row_num] = true
-
end
-
-
end
-
-
-
# params[:participant_id]
-
# params[:versions] an array (in asc order) of all versions of the review file
-
# params[:diff_with_file_id] - Id of current file to be diffed with
-
# params[:current_version_id] the if of current version of file
-
1
def show_code_file_diff
-
@participant = AssignmentParticipant.find(params[:participant_id])
-
-
# Get the filepath of both the files.
-
older_file = ReviewFile.find(params[:current_version_id])
-
newer_file = ReviewFile.find(params[:diff_with_file_id])
-
-
@current_review_file = older_file
-
-
@version_fileId_map = Hash.new
-
params[:versions].each do |each_version|
-
this_file = ReviewFile.get_file(
-
ReviewFilesHelper::get_code_review_file_dir(@participant),
-
each_version, File.basename(@current_review_file.filepath))
-
@version_fileId_map[each_version] = this_file ? this_file.id : nil
-
end
-
-
# Swap them if older is more recent than newer
-
if older_file.version_number > newer_file.version_number
-
temp = older_file
-
older_file = newer_file
-
newer_file = temp
-
end
-
-
processor = DiffHelper::Processor.new(older_file.filepath, newer_file.filepath)
-
processor.process!
-
-
@first_line_num = []
-
@second_line_num = []
-
@first_offset = []
-
@second_offset = []
-
first_count = 0
-
second_count = 0
-
@offsetswithcomments_file1 = []
-
@offsetswithcomments_file2 = []
-
-
@first_offset << 0
-
@second_offset << 0
-
-
for i in (0..processor.absolute_line_num)
-
-
if i > 0
-
@first_offset << (@first_offset[i-1] + processor.first_file_array[i-1].size)
-
@second_offset << (@second_offset[i-1] + processor.second_file_array[i-1].size)
-
end
-
-
first = processor.first_file_array[i].to_s
-
-
if(first != "")
-
@first_line_num << first_count+1
-
first_count += 1
-
else # empty
-
@first_line_num << nil
-
end
-
-
second = processor.second_file_array[i].to_s
-
-
if(second != "")
-
@second_line_num << second_count+1
-
second_count += 1
-
else
-
@second_line_num << nil
-
end
-
-
# Remove newlines at the end of this line of code
-
if(processor.first_file_array[i] != nil)
-
processor.first_file_array[i] = processor.first_file_array[i].chomp
-
end
-
if(processor.second_file_array[i] != nil)
-
processor.second_file_array[i] = processor.second_file_array[i].chomp
-
end
-
-
end
-
-
older_version_comments = ReviewComment.find_all_by_review_file_id(older_file.id)
-
newer_version_comments = ReviewComment.find_all_by_review_file_id(newer_file.id)
-
-
@shareObj = Hash.new()
-
@shareObj['linearray1'] = processor.first_file_array
-
@shareObj['linearray2'] = processor.second_file_array
-
@shareObj['comparator'] = processor.comparison_array
-
@shareObj['linenumarray1'] = @first_line_num
-
@shareObj['linenumarray2'] = @second_line_num
-
@shareObj['offsetarray1'] = @first_offset
-
@shareObj['offsetarray2'] = @second_offset
-
@file_on_left = older_file
-
@file_on_right = newer_file
-
-
-
# REFACTOR: Code Duplication
-
-
@highlight_cell_left_file = Hash.new
-
older_version_comments.each do |each_comment|
-
table_row_num = @first_offset.index(each_comment.file_offset)
-
table_row_num = @first_offset.length + 1 unless table_row_num
-
-
# Increment table_row_num until a non "" string is encountered in @first_line_num
-
while (@first_line_num[table_row_num].nil? and
-
table_row_num < @first_line_num.length)
-
table_row_num += 1
-
end
-
-
@highlight_cell_left_file[table_row_num] = true
-
end
-
-
-
@highlight_cell_right_file = Hash.new
-
newer_version_comments.each do |each_comment|
-
table_row_num = @second_offset.index(each_comment.file_offset)
-
table_row_num = @second_offset.length + 1 unless table_row_num
-
-
# Increment table_row_num until a non "" string is encountered in @second_line_num
-
while (@second_line_num[table_row_num].nil? and
-
table_row_num < @second_line_num.length)
-
table_row_num += 1
-
end
-
-
@highlight_cell_right_file[table_row_num] = true
-
end
-
-
end
-
-
-
-
1
def submit_comment
-
@comment = ReviewComment.new
-
@comment.review_file_id = params[:file_id]
-
@comment.file_offset = params[:file_offset]
-
@comment.comment_content = params[:comment_content].gsub("\n", " ")
-
@comment.reviewer_participant_id = AssignmentParticipant.find_by_user_id(
-
session[:user].id).id
-
@comment.save
-
end
-
-
# Needs params[:file_id], params[:file_offset]
-
1
def get_comments
-
all_comment_contents = []
-
ReviewComment.find_all_by_review_file_id_and_file_offset(
-
params[:file_id], params[:file_offset]).each { |comment|
-
all_comment_contents << comment.comment_content.gsub("\n", " ")
-
}
-
comments_in_table = ReviewCommentsHelper::construct_comments_table(
-
all_comment_contents)
-
-
respond_to do |format|
-
format.js { render :json => comments_in_table }
-
end
-
end
-
-
1
private
-
-
1
def render_error_page(exception = nil)
-
redirect_to :controller => 'content_pages', :action => 'show',
-
:id => SystemSettings.find(:first).not_found_page_id
-
-
end
-
-
end
-
1
class ReviewMappingController < ApplicationController
-
1
auto_complete_for :user, :name
-
1
use_google_charts
-
1
helper :dynamic_review_assignment
-
1
helper :submitted_content
-
-
1
def auto_complete_for_user_name
-
name = params[:user][:name]+"%"
-
assignment_id = session[:contributor].parent_id
-
@users = User.find(:all, :include => :participants,
-
:conditions => ['participants.type = "AssignmentParticipant" and users.name like ? and participants.parent_id = ?',name,assignment_id],
-
:order => 'name')
-
-
render :inline => "<%= auto_complete_result @users, 'name' %>", :layout => false
-
end
-
-
1
def select_reviewer
-
assignment = Assignment.find(params[:id])
-
@contributor = assignment.get_contributor(params[:contributor_id])
-
session[:contributor] = @contributor
-
end
-
-
1
def select_metareviewer
-
@mapping = ResponseMap.find(params[:id])
-
end
-
-
1
def add_reviewer
-
assignment = Assignment.find(params[:id])
-
msg = String.new
-
begin
-
-
user = User.from_params(params)
-
-
regurl = url_for :action => 'add_user_to_assignment',
-
:id => assignment.id,
-
:user_id => user.id,
-
:contributor_id => params[:contributor_id]
-
-
# Get the assignment's participant corresponding to the user
-
reviewer = get_reviewer(user,assignment,regurl)
-
#ACS Removed the if condition(and corressponding else) which differentiate assignments as team and individual assignments
-
# to treat all assignments as team assignments
-
if TeamReviewResponseMap.find(:first, :conditions => ['reviewee_id = ? and reviewer_id = ?',params[:id],reviewer.id]).nil?
-
TeamReviewResponseMap.create(:reviewee_id => params[:contributor_id], :reviewer_id => reviewer.id, :reviewed_object_id => assignment.id)
-
else
-
raise "The reviewer, \""+reviewer.name+"\", is already assigned to this contributor."
-
end
-
-
rescue
-
msg = $!
-
end
-
redirect_to :action => 'list_mappings', :id => assignment.id, :msg => msg
-
end
-
-
# Get all the available submissions
-
1
def show_available_submissions
-
assignment = Assignment.find(params[:assignment_id])
-
reviewer = AssignmentParticipant.find_by_user_id_and_parent_id(params[:reviewer_id], assignment.id)
-
requested_topic_id = params[:topic_id]
-
@available_submissions = Hash.new
-
@available_submissions = DynamicReviewAssignmentHelper::review_assignment(assignment.id ,
-
reviewer.id,
-
requested_topic_id ,
-
Assignment::RS_STUDENT_SELECTED)
-
end
-
-
# Assign self to a submission
-
1
def add_self_reviewer
-
assignment = Assignment.find(params[:assignment_id])
-
reviewer = AssignmentParticipant.find_by_user_id_and_parent_id(params[:reviewer_id], assignment.id)
-
submission = AssignmentParticipant.find_by_id_and_parent_id(params[:submission_id],assignment.id)
-
-
if submission.nil?
-
flash[:error] = "Could not find a submission to review for the specified topic, please choose another topic to continue."
-
redirect_to :controller => 'student_review', :action => 'list', :id => reviewer.id
-
else
-
-
begin
-
#ACS Removed the if condition(and corressponding else) which differentiate assignments as team and individual assignments
-
# to treat all assignments as team assignments
-
contributor = get_team_from_submission(submission)
-
if TeamReviewResponseMap.find(:first, :conditions => ['reviewee_id = ? and reviewer_id = ?', contributor.id, reviewer.id]).nil?
-
TeamReviewResponseMap.create(:reviewee_id => contributor.id,
-
:reviewer_id => reviewer.id,
-
:reviewed_object_id => assignment.id)
-
else
-
raise "The reviewer, \""+reviewer.name+"\", is already assigned to this contributor."
-
end
-
redirect_to :controller => 'student_review', :action => 'list', :id => reviewer.id
-
rescue
-
redirect_to :controller => 'student_review', :action => 'list', :id => reviewer.id, :msg => $!
-
end
-
-
end
-
end
-
-
# Looks up the team from the submission.
-
1
def get_team_from_submission(submission)
-
# Get the list of teams for this assignment.
-
teams = AssignmentTeam.find_all_by_parent_id( submission.parent_id)
-
-
teams.each do |team|
-
team.teams_users.each do |team_member|
-
if team_member.user_id == submission.user_id
-
# Found the team, return it!
-
return team
-
end
-
end
-
end
-
-
# No team found
-
return nil
-
end
-
-
1
def assign_reviewer_dynamically
-
begin
-
assignment = Assignment.find(params[:assignment_id])
-
reviewer = AssignmentParticipant.find_by_user_id_and_parent_id(params[:reviewer_id], assignment.id)
-
-
unless params[:i_dont_care]
-
topic = (params[:topic_id].nil?) ? nil : SignUpTopic.find(params[:topic_id])
-
else
-
topic = assignment.candidate_topics_to_review.to_a.shuffle[0] rescue nil
-
end
-
-
assignment.assign_reviewer_dynamically(reviewer, topic)
-
-
rescue Exception => e
-
flash[:alert] = (e.nil?) ? $! : e
-
end
-
-
redirect_to :controller => 'student_review', :action => 'list', :id => reviewer.id
-
end
-
-
1
def assign_metareviewer_dynamically
-
begin
-
assignment = Assignment.find(params[:assignment_id])
-
metareviewer = AssignmentParticipant.find_by_user_id_and_parent_id(params[:metareviewer_id], assignment.id)
-
-
assignment.assign_metareviewer_dynamically(metareviewer)
-
-
rescue Exception => e
-
flash[:alert] = (e.nil?) ? $! : e
-
end
-
-
redirect_to :controller => 'student_review', :action => 'list', :id => metareviewer.id
-
end
-
-
1
def add_metareviewer
-
mapping = ResponseMap.find(params[:id])
-
msg = String.new
-
begin
-
user = User.from_params(params)
-
-
regurl = url_for :action => 'add_user_to_assignment', :id => mapping.id, :user_id => user.id
-
reviewer = get_reviewer(user,mapping.assignment,regurl)
-
if MetareviewResponseMap.find(:first, :conditions => ['reviewed_object_id = ? and reviewer_id = ?',mapping.id,reviewer.id]) != nil
-
raise "The metareviewer \""+reviewer.user.name+"\" is already assigned to this reviewer."
-
end
-
MetareviewResponseMap.create(:reviewed_object_id => mapping.id,
-
:reviewer_id => reviewer.id,
-
:reviewee_id => mapping.reviewer.id)
-
rescue
-
msg = $!
-
end
-
redirect_to :action => 'list_mappings', :id => mapping.assignment.id, :msg => msg
-
end
-
-
1
def get_reviewer(user,assignment,reg_url)
-
reviewer = AssignmentParticipant.find_by_user_id_and_parent_id(user.id,assignment.id)
-
if reviewer.nil?
-
raise "\"#{user.name}\" is not a participant in the assignment. Please <a href='#{reg_url}'>register</a> this user to continue."
-
end
-
return reviewer
-
end
-
-
-
1
def add_user_to_assignment
-
if params[:contributor_id]
-
assignment = Assignment.find(params[:id])
-
else
-
mapping = ResponseMap.find(params[:id])
-
assignment = mapping.assignment
-
end
-
-
user = User.find(params[:user_id])
-
begin
-
assignment.add_participant(user.name)
-
rescue
-
flash[:error] = $!
-
end
-
if params[:contributor_id]
-
redirect_to :action => 'add_reviewer', :id => params[:id], :user_id => user.id, :contributor_id => params[:contributor_id]
-
else
-
redirect_to :action => 'add_metareviewer', :id => params[:id], :user_id => user.id
-
end
-
end
-
-
-
1
def delete_all_reviewers_and_metareviewers
-
assignment = Assignment.find(params[:id])
-
-
failedCount = ResponseMap.delete_mappings(assignment.review_mappings,params[:force])
-
if failedCount > 0
-
url_yes = url_for :action => 'delete_all_reviewers_and_metareviewers', :id => params[:id], :force => 1
-
url_no = url_for :action => 'delete_all_reviewers_and_metareviewers', :id => params[:id]
-
flash[:error] = "A delete action failed:<br/>#{failedCount} reviews exist for these mappings. Delete these mappings anyway? <a href='#{url_yes}'>Yes</a> | <a href='#{url_no}'>No</a><BR/>"
-
else
-
flash[:note] = "All review mappings for this assignment have been deleted."
-
end
-
redirect_to :action => 'list_mappings', :id => params[:id]
-
end
-
-
1
def delete_all_reviewers
-
assignment = Assignment.find(params[:id])
-
contributor = assignment.get_contributor(params[:contributor_id])
-
mappings = contributor.review_mappings
-
-
failedCount = ResponseMap.delete_mappings(mappings, params[:force])
-
if failedCount > 0
-
url_yes = url_for :action => 'delete_all_reviewers', :id => assignment.id, :contributor_id => contributor.id, :force => 1
-
url_no = url_for :action => 'delete_all_reviewers', :id => assignment.id, :contributor_id => contributor.id
-
flash[:error] = "A delete action failed:<br/>#{failedCount} reviews and/or metareviews exist for these mappings. Delete these mappings anyway? <a href='#{url_yes}'>Yes</a> | <a href='#{url_no}'>No</a><BR/>"
-
else
-
flash[:note] = "All review mappings for \""+contributor.name+"\" have been deleted."
-
end
-
redirect_to :action => 'list_mappings', :id => assignment.id
-
end
-
-
1
def delete_all_metareviewers
-
mapping = ResponseMap.find(params[:id])
-
mmappings = MetareviewResponseMap.find_all_by_reviewed_object_id(mapping.id)
-
-
failedCount = ResponseMap.delete_mappings(mmappings, params[:force])
-
if failedCount > 0
-
url_yes = url_for :action => 'delete_all_metareviewers', :id => mapping.id, :force => 1
-
url_no = url_for :action => 'delete_all_metareviewers', :id => mapping.id
-
flash[:error] = "A delete action failed:<br/>#{failedCount} metareviews exist for these mappings. Delete these mappings anyway? <a href='#{url_yes}'>Yes</a> | <a href='#{url_no}'>No</a><BR/>"
-
else
-
flash[:note] = "All metareview mappings for contributor \""+mapping.reviewee.name+"\" and reviewer \""+mapping.reviewer.name+"\" have been deleted."
-
end
-
redirect_to :action => 'list_mappings', :id => mapping.assignment.id
-
end
-
-
1
def delete_reviewer
-
mapping = ResponseMap.find(params[:id])
-
assignment_id = mapping.assignment.id
-
begin
-
mapping.delete
-
flash[:note] = "The review mapping for \""+mapping.reviewee.name+"\" and \""+mapping.reviewer.name+"\" have been deleted."
-
rescue
-
flash[:error] = "A delete action failed:<br/>" + $! + "Delete this mapping anyway? <a href='/review_mapping/delete_review/"+mapping.id.to_s+"'>Yes</a> | <a href='/review_mapping/list_mappings/#{assignment_id}'>No</a>"
-
end
-
redirect_to :action => 'list_mappings', :id => assignment_id
-
end
-
-
1
def delete_metareviewer
-
mapping = MetareviewResponseMap.find(params[:id])
-
assignment_id = mapping.assignment.id
-
flash[:note] = "The metareview mapping for "+mapping.reviewee.name+" and "+mapping.reviewer.name+" have been deleted."
-
-
begin
-
mapping.delete
-
rescue
-
flash[:error] = "A delete action failed:<br/>" + $! + "<a href='/review_mapping/delete_metareview/"+mapping.id.to_s+"'>Delete this mapping anyway>?"
-
end
-
-
redirect_to :action => 'list_mappings', :id => assignment_id
-
end
-
-
1
def release_reservation
-
mapping = ResponseMap.find(params[:id])
-
student_id = mapping.reviewer_id
-
mapping.delete
-
redirect_to :controller => 'student_review', :action => 'list', :id => student_id
-
end
-
-
1
def delete_review
-
mapping = ResponseMap.find(params[:id])
-
mapping.response.delete
-
redirect_to :action => 'delete_reviewer', :id => mapping.id
-
end
-
-
1
def delete_metareview
-
mapping = MetareviewResponseMap.find(params[:id])
-
metareview = mapping.response
-
metareview.delete
-
mapping.delete
-
redirect_to :action => 'list_mappings', :id => mapping.review_mapping.assignment_id
-
end
-
-
1
def list
-
all_assignments = Assignment.find(:all, :order => 'name', :conditions => ["instructor_id = ?",session[:user].id])
-
-
letter = params[:letter]
-
if letter == nil
-
letter = all_assignments.first.name[0,1].downcase
-
end
-
-
@letters = Array.new
-
@assignments = Assignment.paginate(:page => params[:page], :order => 'name',:per_page => 10, :conditions => ["instructor_id = ? and substring(name,1,1) = ?",session[:user].id, letter])
-
-
all_assignments.each {
-
| assignObj |
-
first = assignObj.name[0,1].downcase
-
if not @letters.include?(first)
-
@letters << first
-
end
-
}
-
end
-
-
1
def list_mappings
-
if params[:msg]
-
flash[:error] = params[:msg]
-
end
-
@assignment = Assignment.find(params[:id])
-
#ACS Removed the if condition(and corressponding else) which differentiate assignments as team and individual assignments
-
# to treat all assignments as team assignments
-
@items = AssignmentTeam.find_all_by_parent_id(@assignment.id)
-
@items.sort!{|a,b| a.name <=> b.name}
-
end
-
-
1
def list_sortable
-
@assignment = Assignment.find(params[:id])
-
@entries = Array.new
-
index = 0
-
#ACS Removed the if condition(and corressponding else) which differentiate assignments as team and individual assignments
-
# to treat all assignments as team assignments
-
contributors = AssignmentTeam.find_all_by_parent_id(@assignment.id)
-
contributors.sort!{|a,b| a.name <=> b.name}
-
contributors.each{
-
|contrib|
-
review_mappings = ResponseMap.find_all_by_reviewed_object_id_and_reviewee_id(@assignment.id,contrib.id)
-
-
if review_mappings.length == 0
-
single = Array.new
-
single[0] = contrib.name
-
single[1] = " "
-
single[2] = " "
-
@entries[index] = single
-
index += 1
-
else
-
review_mappings.sort!{|a,b| a.reviewer.name <=> b.reviewer.name}
-
review_mappings.each{
-
|review_map|
-
metareview_mappings = MetareviewResponseMap.find_all_by_reviewed_object_id(review_map.id)
-
if metareview_mappings.length == 0
-
single = Array.new
-
single[0] = contrib.name
-
single[1] = review_map.reviewer.name
-
single[2] = " "
-
@entries[index] = single
-
index += 1
-
else
-
metareview_mappings.sort!{|a,b| a.reviewer.name <=> b.reviewer.name}
-
metareview_mappings.each{
-
|metareview_map|
-
single = Array.new
-
single[0] = contrib.name
-
single[1] = review_map.reviewer.name
-
if metareview_map.review_reviewer == nil
-
single[2] = metareview_map.reviewer.name
-
else
-
single[2] = metareview_map.review_reviewer.name
-
end
-
@entries[index] = single
-
index += 1
-
}
-
end
-
}
-
end
-
}
-
end
-
-
1
def generate_reviewer_mapping
-
assignment = Assignment.find(params[:id])
-
-
if params[:selection]
-
mapping_strategy = {}
-
params[:selection].each do |a|
-
if a[0] =~ /^m_/
-
mapping_strategy[a[0]] = a[1]
-
end
-
end
-
else
-
mapping_strategy = 1
-
end
-
-
if assignment.update_attributes(params[:assignment])
-
begin
-
assignment.assign_reviewers(mapping_strategy)
-
rescue
-
flash[:error] = "Reviewer assignment failed. Cause: " + $!
-
ensure
-
redirect_to :action => 'list_mappings', :id => assignment.id
-
end
-
else
-
@wiki_types = WikiType.find(:all)
-
redirect_to :action => 'list_mappings', :id => assignment.id
-
end
-
end
-
-
# This is for staggered deadline assignment
-
1
def automatic_reviewer_mapping
-
assignment = Assignment.find(params[:id])
-
message = assignment.assign_reviewers_staggered(params[:assignment][:num_reviews], params[:assignment][:num_metareviews])
-
flash[:note] = message
-
redirect_to :action => 'list_mappings', :id => assignment.id
-
end
-
-
-
1
def select_mapping
-
@assignment = Assignment.find(params[:id])
-
@review_strategies = ReviewStrategy.find(:all, :order => 'name')
-
@mapping_strategies = MappingStrategy.find(:all, :order => 'name')
-
end
-
-
1
def review_report
-
# Get the assignment id and set it in an instance variable which will be used in view
-
@id = params[:id]
-
@assignment = Assignment.find(params[:id])
-
#ACS Removed the if condition(and corressponding else) which differentiate assignments as team and individual assignments
-
# to treat all assignments as team assignments
-
@type = "TeamReviewResponseMap"
-
-
if params[:user].nil?
-
# This is not a search, so find all reviewers for this assignment
-
@reviewers = ResponseMap.find(:all,:select => "DISTINCT reviewer_id", :conditions => ["reviewed_object_id = ? and type = ? ", @id, @type] )
-
else
-
# This is a search, so find reviewers by user's full name
-
us = User.find(:all, :select => "DISTINCT id", :conditions => ["fullname LIKE ?", '%'+params[:user][:fullname]+'%'])
-
participants = Participant.find(:all, :select => "DISTINCT id", :conditions => ["user_id IN (?) and parent_id = ?", us, @assignment.id] )
-
@reviewers = ResponseMap.find(:all,:select => "DISTINCT reviewer_id", :conditions => ["reviewed_object_id = ? and type = ? and reviewer_id IN (?) ", @id, @type, participants] )
-
end
-
-
# Arranged as the hash @review_scores[reveiwer_id][reviewee_id] = score for this particular assignment
-
@review_scores = @assignment.compute_reviews_hash
-
end
-
-
1
def distribution
-
-
@assignment = Assignment.find(params[:id])
-
-
@scores = [0,0,0,0,0,0,0,0,0,0]
-
#ACS Removed the if condition(and corressponding else) which differentiate assignments as team and individual assignments
-
# to treat all assignments as team assignments
-
teams = Team.find_all_by_parent_id(params[:id])
-
objtype = "TeamReviewResponseMap"
-
-
teams.each do |team|
-
score_cache = ScoreCache.find(:first, :conditions => ["reviewee_id = ? and object_type = ?",team.id, objtype])
-
t_score = 0
-
if score_cache!= nil
-
t_score = score_cache.score
-
end
-
if (t_score != 0)
-
@scores[(t_score/10).to_i] = @scores[(t_score/10).to_i] + 1
-
end
-
end
-
-
-
dataset = GoogleChartDataset.new :data => @scores, :color => '9A0000'
-
data = GoogleChartData.new :datasets => [dataset]
-
axis = GoogleChartAxis.new :axis => [GoogleChartAxis::BOTTOM, GoogleChartAxis::LEFT]
-
@chart1 = GoogleBarChart.new :width => 500, :height => 200
-
@chart1.data = data
-
@chart1.axis = axis
-
-
-
###################### Second Graph ####################
-
-
max_score = 0
-
@review_distribution =[0,0,0,0,0,0,0,0,0,0]
-
### For every responsemapping for this assgt, find the reviewer_id and reviewee_id #####
-
@reviews_not_done = 0
-
response_maps = ResponseMap.find(:all, :conditions =>["reviewed_object_id = ? and type = ?", @assignment.id, objtype])
-
review_report = @assignment.compute_reviews_hash
-
for response_map in response_maps
-
score_for_this_review = review_report[response_map.reviewer_id][response_map.reviewee_id]
-
if(score_for_this_review != 0)
-
@review_distribution[(score_for_this_review/10-1).to_i] = @review_distribution[(score_for_this_review/10-1).to_i] + 1
-
if (@review_distribution[(score_for_this_review/10-1).to_i] > max_score)
-
max_score = @review_distribution[(score_for_this_review/10-1).to_i]
-
end
-
else
-
@reviews_not_done +=1
-
end
-
end
-
-
dataset2 = GoogleChartDataset.new :data => @review_distribution, :color => '9A0000'
-
data2 = GoogleChartData.new :datasets => [dataset2]
-
axis2 = GoogleChartAxis.new :axis => [GoogleChartAxis::BOTTOM, GoogleChartAxis::LEFT]
-
-
@chart2 = GoogleBarChart.new :width => 500, :height => 200
-
@chart2.data = data2
-
@chart2.axis = axis2
-
-
end
-
-
end
-
1
class RolesController < ApplicationController
-
-
# GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
-
1
verify method: :post, only: [ :destroy, :create, :update ], redirect_to: Role
-
-
1
def index
-
6
@roles = Role.order(:name)
-
end
-
-
1
def list
-
2
redirect_to Role
-
end
-
-
1
def show
-
4
@role = Role.find(params[:id])
-
4
@rps = RolesPermission.find_for_role(@role.id)
-
4
@roles = @role.get_parents
-
4
foreign
-
end
-
-
1
def new
-
2
@role = Role.new
-
2
foreign()
-
end
-
-
1
def create
-
2
@role = Role.new(params[:role])
-
2
if @role.save
-
2
Role.rebuild_cache
-
2
flash[:notice] = 'Role was successfully created.'
-
2
redirect_to Role
-
else
-
foreign
-
render :action => 'new'
-
end
-
end
-
-
1
def edit
-
1
@role = Role.find(params[:id])
-
1
foreign
-
end
-
-
1
def update
-
1
@role = Role.find(params[:id])
-
1
if @role.update_attributes(params[:role])
-
1
Role.rebuild_cache
-
1
@role = Role.find(params[:id])
-
1
flash[:notice] = 'Role was successfully updated.'
-
1
redirect_to :action => 'show', :id => @role.id
-
else
-
foreign
-
render :action => 'edit'
-
end
-
end
-
-
1
def destroy
-
1
Role.find(params[:id]).destroy
-
1
redirect_to Role
-
end
-
-
1
protected
-
-
1
def foreign
-
7
@other_roles = @role.other_roles
-
-
7
@users = @role.users
-
end
-
end
-
1
class RolesPermissionsController < ApplicationController
-
-
# GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
-
verify :method => :post, :only => [ :destroy, :create, :update ],
-
1
:redirect_to => { :action => :list }
-
-
1
def index
-
list
-
render :action => 'list'
-
end
-
-
1
def list
-
@roles_permissions = RolesPermission.paginate(:page => params[:page], :per_page => 10)
-
end
-
-
1
def show
-
@roles_permission = RolesPermission.find(params[:id])
-
end
-
-
1
def new
-
@roles_permission = RolesPermission.new
-
end
-
-
1
def new_permission_for_role
-
@roles_permission = RolesPermission.new
-
@roles_permission.role_id = params[:id]
-
@role = Role.find(params[:id])
-
@permissions = Permission.find_not_for_role(params[:id])
-
end
-
-
1
def create
-
@roles_permission = RolesPermission.new(params[:roles_permission])
-
if @roles_permission.save
-
flash[:notice] = 'RolesPermission was successfully created.'
-
redirect_to :controller => 'roles', :action => 'show',
-
:id => @roles_permission.role_id
-
else
-
render :action => 'new'
-
end
-
end
-
-
1
def edit
-
@roles_permission = RolesPermission.find(params[:id])
-
end
-
-
1
def update
-
@roles_permission = RolesPermission.find(params[:id])
-
if @roles_permission.update_attributes(params[:roles_permission])
-
flash[:notice] = 'RolesPermission was successfully updated.'
-
redirect_to :action => 'show', :id => @roles_permission
-
else
-
render :action => 'edit'
-
end
-
end
-
-
1
def destroy
-
rp = RolesPermission.find(params[:id])
-
role = rp.role_id
-
rp.destroy
-
redirect_to :controller => 'roles', :action => 'show', :id => role
-
end
-
end
-
#contains all functions related to management of the signup sheet for an assignment
-
#functions to add new topics to an assignment, edit properties of a particular topic, delete a topic, etc
-
#are included here
-
-
#A point to be taken into consideration is that :id (except when explicitly stated) here means topic id and not assignment id
-
#(this is referenced as :assignment id in the params has)
-
#The way it works is that assignments have their own id's, so do topics. A topic has a foreign key dependecy on the assignment_id
-
#Hence each topic has a field called assignment_id which points which can be used to identify the assignment that this topic belongs
-
#to
-
-
1
class SignUpSheetController < ApplicationController
-
1
require 'rgl/adjacency'
-
1
require 'rgl/dot'
-
1
require 'graph/graphviz_dot'
-
1
require 'rgl/topsort'
-
-
#Includes functions for team management. Refer /app/helpers/ManageTeamHelper
-
1
include ManageTeamHelper
-
#Includes functions for Dead line management. Refer /app/helpers/DeadLineHelper
-
1
include DeadlineHelper
-
-
# GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
-
verify :method => :post, :only => [:destroy, :create, :update],
-
1
:redirect_to => {:action => :list}
-
-
#This displays a page that lists all the available topics for an assignment.
-
#Contains links that let an admin or Instructor edit, delete, view enrolled/waitlisted members for each topic
-
#Also contains links to delete topics and modify the deadlines for individual topics. Staggered means that different topics
-
#can have different deadlines.
-
1
def add_signup_topics_staggered
-
load_add_signup_topics(params[:id])
-
-
@review_rounds = Assignment.find(params[:id]).get_review_rounds
-
@topics = SignUpTopic.find_all_by_assignment_id(params[:id])
-
-
#Use this until you figure out how to initialize this array
-
@duedates = SignUpTopic.find_by_sql("SELECT s.id as topic_id FROM sign_up_topics s WHERE s.assignment_id = " + params[:id].to_s)
-
-
if !@topics.nil?
-
i=0
-
@topics.each { |topic|
-
-
@duedates[i]['t_id'] = topic.id
-
@duedates[i]['topic_identifier'] = topic.topic_identifier
-
@duedates[i]['topic_name'] = topic.topic_name
-
-
for j in 1..@review_rounds
-
if j == 1
-
duedate_subm = TopicDeadline.find_by_topic_id_and_deadline_type_id(topic.id, DeadlineType.find_by_name('submission').id)
-
duedate_rev = TopicDeadline.find_by_topic_id_and_deadline_type_id(topic.id, DeadlineType.find_by_name('review').id)
-
else
-
duedate_subm = TopicDeadline.find_by_topic_id_and_deadline_type_id_and_round(topic.id, DeadlineType.find_by_name('resubmission').id, j)
-
duedate_rev = TopicDeadline.find_by_topic_id_and_deadline_type_id_and_round(topic.id, DeadlineType.find_by_name('rereview').id, j)
-
end
-
if !duedate_subm.nil? && !duedate_rev.nil?
-
@duedates[i]['submission_'+ j.to_s] = DateTime.parse(duedate_subm['due_at'].to_s).strftime("%Y-%m-%d %H:%M:%S")
-
@duedates[i]['review_'+ j.to_s] = DateTime.parse(duedate_rev['due_at'].to_s).strftime("%Y-%m-%d %H:%M:%S")
-
else
-
#the topic is new. so copy deadlines from assignment
-
set_of_due_dates = DueDate.find_all_by_assignment_id(params[:id])
-
set_of_due_dates.each { |due_date|
-
create_topic_deadline(due_date, 0, topic.id)
-
}
-
# code execution would have hit the else part during review_round one. So we'll do only round one
-
duedate_subm = TopicDeadline.find_by_topic_id_and_deadline_type_id(topic.id, DeadlineType.find_by_name('submission').id)
-
duedate_rev = TopicDeadline.find_by_topic_id_and_deadline_type_id(topic.id, DeadlineType.find_by_name('review').id)
-
@duedates[i]['submission_'+ j.to_s] = DateTime.parse(duedate_subm['due_at'].to_s).strftime("%Y-%m-%d %H:%M:%S")
-
@duedates[i]['review_'+ j.to_s] = DateTime.parse(duedate_rev['due_at'].to_s).strftime("%Y-%m-%d %H:%M:%S")
-
end
-
-
end
-
duedate_subm = TopicDeadline.find_by_topic_id_and_deadline_type_id(topic.id, DeadlineType.find_by_name('metareview').id)
-
if !duedate_subm.nil?
-
@duedates[i]['submission_'+ (@review_rounds+1).to_s] = DateTime.parse(duedate_subm['due_at'].to_s).strftime("%Y-%m-%d %H:%M:%S")
-
else
-
@duedates[i]['submission_'+ (@review_rounds+1).to_s] = nil
-
end
-
i = i + 1
-
}
-
end
-
end
-
-
#similar to the above function except that all the topics and review/submission rounds have the similar deadlines
-
1
def add_signup_topics
-
load_add_signup_topics(params[:id])
-
end
-
-
#Seems like this function is similar to the above function> we are not quite sure what publishing rights mean. Seems like
-
#the values for the last column in http://expertiza.ncsu.edu/student_task/list are sourced from here
-
1
def view_publishing_rights
-
load_add_signup_topics(params[:id])
-
end
-
-
#retrieves all the data associated with the given assignment. Includes all topics,
-
#participants(people who are doing this assignment) and signed up users (people who have chosen a topic (confirmed or waitlisted)
-
1
def load_add_signup_topics(assignment_id)
-
@id = assignment_id
-
@sign_up_topics = SignUpTopic.find(:all, :conditions => ['assignment_id = ?', assignment_id])
-
@slots_filled = SignUpTopic.find_slots_filled(assignment_id)
-
@slots_waitlisted = SignUpTopic.find_slots_waitlisted(assignment_id)
-
-
@assignment = Assignment.find(assignment_id)
-
#ACS Removed the if condition (and corresponding else) which differentiate assignments as team and individual assignments
-
# to treat all assignments as team assignments
-
@participants = SignedUpUser.find_team_participants(assignment_id)
-
end
-
-
# Prepares the form for adding a new topic. Used in conjuntion with create
-
1
def new
-
@id = params[:id]
-
@sign_up_topic = SignUpTopic.new
-
@sign_up_topic.assignment = Assignment.find(params[:id])
-
@topic = @sign_up_topic
-
end
-
-
#This method is used to create signup topics
-
#In this code params[:id] is the assignment id and not topic id. The intuition is
-
#that assignment id will virtually be the signup sheet id as well as we have assumed
-
#that every assignment will have only one signup sheet
-
1
def create
-
topic = SignUpTopic.find_by_topic_name_and_assignment_id(params[:topic][:topic_name], params[:id])
-
-
#if the topic already exists then update
-
if topic != nil
-
topic.topic_identifier = params[:topic][:topic_identifier]
-
-
#While saving the max choosers you should be careful; if there are users who have signed up for this particular
-
#topic and are on waitlist, then they have to be converted to confirmed topic based on the availability. But if
-
#there are choosers already and if there is an attempt to decrease the max choosers, as of now I am not allowing
-
#it.
-
if SignedUpUser.find_by_topic_id(topic.id).nil? || topic.max_choosers == params[:topic][:max_choosers]
-
topic.max_choosers = params[:topic][:max_choosers]
-
else
-
if topic.max_choosers.to_i < params[:topic][:max_choosers].to_i
-
topic.update_waitlisted_users(params[:topic][:max_choosers])
-
topic.max_choosers = params[:topic][:max_choosers]
-
else
-
flash[:error] = 'Value of maximum choosers can only be increased! No change has been made to max choosers.'
-
end
-
end
-
-
topic.category = params[:topic][:category]
-
#topic.assignment_id = params[:id]
-
topic.save
-
redirect_to_sign_up(params[:id])
-
else
-
#set the values for the new topic and commit to database
-
@sign_up_topic = SignUpTopic.new
-
@sign_up_topic.topic_identifier = params[:topic][:topic_identifier]
-
@sign_up_topic.topic_name = params[:topic][:topic_name]
-
@sign_up_topic.max_choosers = params[:topic][:max_choosers]
-
@sign_up_topic.category = params[:topic][:category]
-
@sign_up_topic.assignment_id = params[:id]
-
@assignment = Assignment.find(params[:id])
-
-
if @assignment.is_microtask?
-
@sign_up_topic.micropayment = params[:topic][:micropayment]
-
end
-
-
if @assignment.staggered_deadline?
-
topic_set = Array.new
-
topic = @sign_up_topic.id
-
-
end
-
-
if @sign_up_topic.save
-
#NotificationLimit.create(:topic_id => @sign_up_topic.id)
-
flash[:notice] = 'Topic was successfully created.'
-
redirect_to_sign_up(params[:id])
-
else
-
render :action => 'new', :id => params[:id]
-
end
-
end
-
end
-
-
#simple function that redirects ti the /add_signup_topics or the /add_signup_topics_staggered page depending on assignment type
-
#staggered means that different topics can have different deadlines.
-
1
def redirect_to_sign_up(assignment_id)
-
assignment = Assignment.find(assignment_id)
-
if assignment.staggered_deadline == true
-
redirect_to :action => 'add_signup_topics_staggered', :id => assignment_id
-
else
-
redirect_to :action => 'add_signup_topics', :id => assignment_id
-
end
-
end
-
-
#This method is used to delete signup topics
-
1
def delete
-
@topic = SignUpTopic.find(params[:id])
-
-
if !@topic.nil?
-
@topic.destroy
-
else
-
flash[:error] = "Topic could not be deleted"
-
end
-
-
#if this assignment has staggered deadlines then destroy the dependencies as well
-
if Assignment.find(params[:assignment_id])['staggered_deadline'] == true
-
dependencies = TopicDependency.find_all_by_topic_id(params[:id])
-
if !dependencies.nil?
-
dependencies.each { |dependency| dependency.destroy }
-
end
-
end
-
redirect_to_sign_up(params[:assignment_id])
-
end
-
#prepares the page. shows the form which can be used to enter new values for the different properties of an assignment
-
1
def edit
-
@topic = SignUpTopic.find(params[:id])
-
@assignment_id = params[:assignment_id]
-
end
-
-
#updates the database tables to reflect the new values for the assignment. Used in conjuntion with edit
-
1
def update
-
topic = SignUpTopic.find(params[:id])
-
-
if !topic.nil?
-
topic.topic_identifier = params[:topic][:topic_identifier]
-
-
#While saving the max choosers you should be careful; if there are users who have signed up for this particular
-
#topic and are on waitlist, then they have to be converted to confirmed topic based on the availability. But if
-
#there are choosers already and if there is an attempt to decrease the max choosers, as of now I am not allowing
-
#it.
-
if SignedUpUser.find_by_topic_id(topic.id).nil? || topic.max_choosers == params[:topic][:max_choosers]
-
topic.max_choosers = params[:topic][:max_choosers]
-
else
-
if topic.max_choosers.to_i < params[:topic][:max_choosers].to_i
-
topic.update_waitlisted_users(params[:topic][:max_choosers])
-
topic.max_choosers = params[:topic][:max_choosers]
-
else
-
flash[:error] = 'Value of maximum choosers can only be increased! No change has been made to max choosers.'
-
end
-
end
-
#update tables
-
topic.category = params[:topic][:category]
-
topic.topic_name = params[:topic][:topic_name]
-
topic.micropayment = params[:topic][:micropayment]
-
topic.save
-
else
-
flash[:error] = "Topic could not be updated"
-
end
-
redirect_to_sign_up(params[:assignment_id])
-
end
-
-
1
def signup_topics
-
@assignment_id = params[:id]
-
@sign_up_topics = SignUpTopic.find(:all, :conditions => ['assignment_id = ?', params[:id]])
-
@slots_filled = SignUpTopic.find_slots_filled(params[:id])
-
@slots_waitlisted = SignUpTopic.find_slots_waitlisted(params[:id])
-
@show_actions = true
-
assignment=Assignment.find(params[:id])
-
-
if assignment.due_dates.find_by_deadline_type_id(1)!= nil
-
if !assignment.staggered_deadline? and assignment.due_dates.find_by_deadline_type_id(1).due_at < Time.now
-
@show_actions = false
-
end
-
end
-
-
#ACS Removed the if condition (and corresponding else) which differentiate assignments as team and individual assignments
-
# to treat all assignments as team assignments
-
users_team = SignedUpUser.find_team_users(params[:id],(session[:user].id))
-
-
if users_team.size == 0
-
@selected_topics = nil
-
else
-
#TODO: fix this; cant use 0
-
@selected_topics = otherConfirmedTopicforUser(params[:id], users_team[0].t_id)
-
end
-
end
-
-
-
#this function is used to delete a previous signup
-
1
def delete_signup
-
delete_signup_for_topic(params[:assignment_id], params[:id])
-
redirect_to :action => 'signup_topics', :id => params[:assignment_id]
-
end
-
-
1
def delete_signup_for_topic(assignment_id, topic_id)
-
#find whether assignment is team assignment
-
assignment = Assignment.find(assignment_id)
-
-
#making sure that the drop date deadline hasn't passed
-
dropDate = DueDate.find(:first, :conditions => {:assignment_id => assignment.id, :deadline_type_id => '6'})
-
if (!dropDate.nil? && dropDate.due_at < Time.now)
-
flash[:error] = "You cannot drop this topic because the drop deadline has passed."
-
else
-
#if team assignment find the creator id from teamusers table and teams
-
#ACS Removed the if condition (and corresponding else) which differentiate assignments as team and individual assignments
-
# to treat all assignments as team assignments
-
#users_team will contain the team id of the team to which the user belongs
-
users_team = SignedUpUser.find_team_users(assignment_id,(session[:user].id))
-
signup_record = SignedUpUser.find_by_topic_id_and_creator_id(topic_id, users_team[0].t_id)
-
-
#if a confirmed slot is deleted then push the first waiting list member to confirmed slot if someone is on the waitlist
-
if signup_record.is_waitlisted == false
-
#find the first wait listed user if exists
-
first_waitlisted_user = SignedUpUser.find_by_topic_id_and_is_waitlisted(topic_id, true)
-
-
if !first_waitlisted_user.nil?
-
# As this user is going to be allocated a confirmed topic, all of his waitlisted topic signups should be purged
-
### Bad policy! Should be changed! (once users are allowed to specify waitlist priorities) -efg
-
first_waitlisted_user.is_waitlisted = false
-
first_waitlisted_user.save
-
-
#update the participants details
-
#ACS Removed the if condition (and corresponding else) which differentiate assignments as team and individual assignments
-
# to treat all assignments as team assignments
-
-
user_id = TeamsUser.find(:first, :conditions => {:team_id => first_waitlisted_user.creator_id}).user_id
-
participant = Participant.find_by_user_id_and_parent_id(user_id,assignment.id)
-
-
participant.update_topic_id(topic_id)
-
-
SignUpTopic.cancel_all_waitlists(first_waitlisted_user.creator_id, assignment_id)
-
end
-
end
-
-
if !signup_record.nil?
-
participant = Participant.find_by_user_id_and_parent_id(session[:user].id, assignment_id)
-
#update participant's topic id to nil
-
participant.update_topic_id(nil)
-
signup_record.destroy
-
end
-
end #end condition for 'drop deadline' check
-
end
-
-
1
def signup
-
puts "++++++++++++++++++++++++++++"
-
puts "you called me in sign_up_sheet_controller!"
-
#find the assignment to which user is signing up
-
assignment = Assignment.find(params[:assignment_id])
-
-
#check whether team assignment. This is to decide whether a team_id or user_id should be the creator_id
-
#Always use team_id ACS
-
-
#check whether the user already has a team for this assignment
-
users_team = SignedUpUser.find_team_users(params[:assignment_id],(session[:user].id))
-
if users_team.size == 0
-
#if team is not yet created, create new team.
-
team = AssignmentTeam.create_team_and_node(params[:assignment_id])
-
user = User.find(session[:user].id)
-
teamuser = create_team_users(user, team.id)
-
confirmationStatus = confirmTopic(team.id, params[:id], params[:assignment_id])
-
else
-
confirmationStatus = confirmTopic(users_team[0].t_id, params[:id], params[:assignment_id])
-
end
-
-
redirect_to :action => 'signup_topics', :id => params[:assignment_id]
-
end
-
-
-
-
# When using this method when creating fields, update race conditions by using db transactions
-
1
def slotAvailable?(topic_id)
-
SignUpTopic.slotAvailable?(topic_id)
-
end
-
-
1
def otherConfirmedTopicforUser(assignment_id, creator_id)
-
user_signup = SignedUpUser.find_user_signup_topics(assignment_id, creator_id)
-
user_signup
-
end
-
-
1
def confirmTopic(creator_id, topic_id, assignment_id)
-
#check whether user has signed up already
-
user_signup = otherConfirmedTopicforUser(assignment_id, creator_id)
-
-
sign_up = SignedUpUser.new
-
sign_up.topic_id = params[:id]
-
sign_up.creator_id = creator_id
-
result = false
-
if user_signup.size == 0
-
-
# Using a DB transaction to ensure atomic inserts
-
ActiveRecord::Base.transaction do
-
#check whether slots exist (params[:id] = topic_id) or has the user selected another topic
-
if slotAvailable?(topic_id)
-
sign_up.is_waitlisted = false
-
-
#Update topic_id in participant table with the topic_id
-
participant = Participant.find_by_user_id_and_parent_id(session[:user].id, assignment_id)
-
-
participant.update_topic_id(topic_id)
-
else
-
sign_up.is_waitlisted = true
-
end
-
if sign_up.save
-
result = true
-
end
-
end
-
else
-
#If all the topics choosen by the user are waitlisted,
-
for user_signup_topic in user_signup
-
if user_signup_topic.is_waitlisted == false
-
flash[:error] = "You have already signed up for a topic."
-
return false
-
end
-
end
-
-
# Using a DB transaction to ensure atomic inserts
-
ActiveRecord::Base.transaction do
-
#check whether user is clicking on a topic which is not going to place him in the waitlist
-
if !slotAvailable?(topic_id)
-
sign_up.is_waitlisted = true
-
if sign_up.save
-
result = true
-
end
-
else
-
#if slot exist, then confirm the topic for the user and delete all the waitlist for this user
-
SignUpTopic.cancel_all_waitlists(creator_id, assignment_id)
-
sign_up.is_waitlisted = false
-
sign_up.save
-
participant = Participant.find_by_user_id_and_parent_id(session[:user].id, assignment_id)
-
participant.update_topic_id(topic_id)
-
result = true
-
end
-
end
-
end
-
-
result
-
end
-
-
1
def has_user(user, team_id)
-
if TeamsUser.find_by_team_id_and_user_id(team_id, user.id)
-
return true
-
else
-
return false
-
end
-
end
-
-
#this function is used to prevent injection attacks. A topic *dependent* on another topic cannot be
-
# attempted until the other topic has been completed..
-
1
def save_topic_dependencies
-
# Prevent injection attacks - we're using this in a system() call later
-
params[:assignment_id] = params[:assignment_id].to_i.to_s
-
-
topics = SignUpTopic.find_all_by_assignment_id(params[:assignment_id])
-
topics = topics.collect { |topic|
-
#if there is no dependency for a topic then there wont be a post for that tag.
-
#if this happens store the dependency as "0"
-
if !params['topic_dependencies_' + topic.id.to_s].nil?
-
[topic.id, params['topic_dependencies_' + topic.id.to_s][:dependent_on]]
-
else
-
[topic.id, ["0"]]
-
end
-
}
-
-
# Save the dependency in the topic dependency table
-
TopicDependency.save_dependency(topics)
-
-
node = 'id'
-
dg = build_dependency_graph(topics, node)
-
-
if dg.acyclic?
-
#This method produces sets of vertexes which should have common start time/deadlines
-
set_of_topics = create_common_start_time_topics(dg)
-
set_start_due_date(params[:assignment_id], set_of_topics)
-
@top_sort = dg.topsort_iterator.to_a
-
else
-
flash[:error] = "There may be one or more cycles in the dependencies. Please correct them"
-
end
-
-
-
node = 'topic_name'
-
dg = build_dependency_graph(topics, node) # rebuild with new node name
-
-
graph_output_path = 'public/images/staggered_deadline_assignment_graph'
-
FileUtils::mkdir_p graph_output_path
-
dg.write_to_graphic_file('jpg', "#{graph_output_path}/graph_#{params[:assignment_id]}")
-
-
redirect_to_sign_up(params[:assignment_id])
-
end
-
-
-
#If the instructor needs to explicitly change the start/due dates of the topics
-
#This is true in case of a staggered deadline type assignment. Individual deadlines can
-
# be set on a per topic and per round basis
-
1
def save_topic_deadlines
-
-
due_dates = params[:due_date]
-
-
review_rounds = Assignment.find(params[:assignment_id]).get_review_rounds
-
due_dates.each { |due_date|
-
for i in 1..review_rounds
-
if i == 1
-
topic_deadline_type_subm = DeadlineType.find_by_name('submission').id
-
topic_deadline_type_rev = DeadlineType.find_by_name('review').id
-
else
-
topic_deadline_type_subm = DeadlineType.find_by_name('resubmission').id
-
topic_deadline_type_rev = DeadlineType.find_by_name('rereview').id
-
end
-
-
topic_deadline_subm = TopicDeadline.find_by_topic_id_and_deadline_type_id_and_round(due_date['t_id'].to_i, topic_deadline_type_subm, i)
-
topic_deadline_subm.update_attributes({'due_at' => due_date['submission_' + i.to_s]})
-
flash[:error] = "Please enter a valid " + (i > 1 ? "Resubmission deadline " + (i-1).to_s : "Submission deadline") if topic_deadline_subm.errors.length > 0
-
-
topic_deadline_rev = TopicDeadline.find_by_topic_id_and_deadline_type_id_and_round(due_date['t_id'].to_i, topic_deadline_type_rev,i)
-
topic_deadline_rev.update_attributes({'due_at' => due_date['review_' + i.to_s]})
-
flash[:error] = "Please enter a valid Review deadline " + (i > 1 ? (i-1).to_s : "") if topic_deadline_rev.errors.length > 0
-
end
-
-
topic_deadline_subm = TopicDeadline.find_by_topic_id_and_deadline_type_id(due_date['t_id'], DeadlineType.find_by_name('metareview').id)
-
topic_deadline_subm.update_attributes({'due_at' => due_date['submission_' + (review_rounds+1).to_s]})
-
flash[:error] = "Please enter a valid Meta review deadline" if topic_deadline_subm.errors.length > 0
-
}
-
-
redirect_to_sign_up(params[:assignment_id])
-
end
-
-
#used by save_topic_dependencies. The dependency graph is a partial ordering of topics ... some topics need to be done
-
# before others can be attempted.
-
1
def build_dependency_graph(topics,node)
-
dg = RGL::DirectedAdjacencyGraph.new
-
-
#create a graph of the assignment with appropriate dependency
-
topics.collect { |topic|
-
topic[1].each { |dependent_node|
-
edge = Array.new
-
#if a topic is not dependent on any other topic
-
dependent_node = dependent_node.to_i
-
if dependent_node == 0
-
edge.push("fake")
-
else
-
#if we want the topic names to be displayed in the graph replace node to topic_name
-
edge.push(SignUpTopic.find(dependent_node)[node])
-
end
-
edge.push(SignUpTopic.find(topic[0])[node])
-
dg.add_edges(edge)
-
}
-
}
-
#remove the fake vertex
-
dg.remove_vertex("fake")
-
dg
-
end
-
#used by save_topic_dependencies. Do not know how this works
-
1
def create_common_start_time_topics(dg)
-
dg_reverse = dg.clone.reverse()
-
set_of_topics = Array.new
-
-
while !dg_reverse.empty?
-
i = 0
-
temp_vertex_array = Array.new
-
dg_reverse.each_vertex { |vertex|
-
if dg_reverse.out_degree(vertex) == 0
-
temp_vertex_array.push(vertex)
-
end
-
}
-
#this cannot go inside the if statement above
-
temp_vertex_array.each { |vertex|
-
dg_reverse.remove_vertex(vertex)
-
}
-
set_of_topics.insert(i, temp_vertex_array)
-
i = i + 1
-
end
-
set_of_topics
-
end
-
-
1
def create_topic_deadline(due_date, offset, topic_id)
-
topic_deadline = TopicDeadline.new
-
topic_deadline.topic_id = topic_id
-
topic_deadline.due_at = DateTime.parse(due_date.due_at.to_s) + offset.to_i
-
topic_deadline.deadline_type_id = due_date.deadline_type_id
-
topic_deadline.late_policy_id = due_date.late_policy_id
-
topic_deadline.submission_allowed_id = due_date.submission_allowed_id
-
topic_deadline.review_allowed_id = due_date.review_allowed_id
-
topic_deadline.resubmission_allowed_id = due_date.resubmission_allowed_id
-
topic_deadline.rereview_allowed_id = due_date.rereview_allowed_id
-
topic_deadline.review_of_review_allowed_id = due_date.review_of_review_allowed_id
-
topic_deadline.round = due_date.round
-
topic_deadline.save
-
end
-
-
1
def set_start_due_date(assignment_id, set_of_topics)
-
-
#Remember, in create_common_start_time_topics function we reversed the graph so reverse it back
-
set_of_topics = set_of_topics.reverse
-
-
set_of_topics_due_dates = Array.new
-
i=0
-
days_between_submissions = Assignment.find(assignment_id)['days_between_submissions'].to_i
-
set_of_topics.each { |set_of_topic|
-
set_of_due_dates = nil
-
if i==0
-
#take the first set from the table which user stores
-
set_of_due_dates = DueDate.find_all_by_assignment_id(assignment_id)
-
offset = 0
-
else
-
set_of_due_dates = TopicDeadline.find_all_by_topic_id(set_of_topics[i-1][0])
-
-
set_of_due_dates.sort! { |a, b| a.due_at <=> b.due_at }
-
-
offset = days_between_submissions
-
end
-
-
set_of_topic.each { |topic_id|
-
#if the due dates have already been created and the save dependency is being clicked,
-
#then delete existing n create again
-
prev_saved_due_dates = TopicDeadline.find_all_by_topic_id(topic_id)
-
-
#Only if there is a dependency for the topic
-
if !prev_saved_due_dates.nil?
-
num_due_dates = prev_saved_due_dates.length
-
#for each due date in the current topic he want to compare it to the previous due date
-
for x in 0..num_due_dates - 1
-
#we don't want the old date to move earlier in time so we save it as the new due date and destroy the old one
-
if DateTime.parse(set_of_due_dates[x].due_at.to_s) + offset.to_i < DateTime.parse(prev_saved_due_dates[x].due_at.to_s)
-
set_of_due_dates[x] = prev_saved_due_dates[x]
-
offset = 0
-
end
-
prev_saved_due_dates[x].destroy
-
end
-
end
-
-
set_of_due_dates.each { |due_date|
-
create_topic_deadline(due_date, offset, topic_id)
-
}
-
}
-
i = i+1
-
}
-
-
end
-
-
#gets team_details to show it on team_details view for a given assignment
-
1
def team_details
-
if !(assignment = Assignment.find(params[:assignment_id])).nil? and !(topic = SignUpTopic.find(params[:id])).nil?
-
@results =ad_info(assignment.id, topic.id)
-
@results.each do |result|
-
result.attributes().each do |attr|
-
if attr[0].equal? "name"
-
@current_team_name = attr[1]
-
end
-
end
-
end
-
@results.each { |result|
-
@team_members = ""
-
TeamsUser.find_all_by_team_id(result[:team_id]).each { |teamuser|
-
puts 'Userblaahsdb asd' +User.find(teamuser.user_id).to_json
-
@team_members+=User.find(teamuser.user_id).name+" "
-
}
-
}
-
#@team_members = find_team_members(topic)
-
end
-
end
-
-
# searches and returns team members for a given team_id
-
1
def find_team_members(team_id)
-
TeamsUser.find_all_by_team_id(team_id).each { |teamuser|
-
team_members+=User.find(teamuser.user_id).handle+" "
-
}
-
end
-
-
# get info related to the ad for partners so that it can be displayed when an assignment_participant
-
# clicks to see ads related to a topic
-
1
def ad_info(assignment_id, topic_id)
-
query = "select t.id as team_id,t.comments_for_advertisement,t.name,su.assignment_id from teams t, signed_up_users s,sign_up_topics su where s.topic_id='"+topic_id.to_s+"' and s.creator_id=t.id and s.topic_id = su.id; "
-
SignUpTopic.find_by_sql(query)
-
end
-
-
1
def create_default_for_microtask
-
assignment_id = params[:id]
-
@sign_up_topic = SignUpTopic.new
-
@sign_up_topic.topic_identifier = 'MT1'
-
@sign_up_topic.topic_name = 'Microtask Topic'
-
@sign_up_topic.max_choosers = '0'
-
@sign_up_topic.micropayment = 0
-
@sign_up_topic.assignment_id = assignment_id
-
-
@assignment = Assignment.find(params[:id])
-
-
if @assignment.staggered_deadline?
-
topic_set = Array.new
-
topic = @sign_up_topic.id
-
-
end
-
-
if @sign_up_topic.save
-
-
flash[:notice] = 'Default Microtask topic was created - please update.'
-
redirect_to_sign_up(assignment_id)
-
else
-
render :action => 'new', :id => assignment_id
-
end
-
end
-
-
-
end
-
#Signup controller has all the functions related to signup for a topic and droppng a selected
-
#topic. These are all actions that a user performs. The following is a brief explanation of what each method does.
-
-
1
class SignupController < ApplicationController
-
# The manage team helper is used to update the create new teams, update teams, delete teams etc. For more information refer
-
# /app/helpers/ManageTeamHelper
-
1
include ManageTeamHelper
-
-
#Displays all the topics available for an assignment, including number of people who can choose the topic, number of
-
#people who have already chosen the topic, etc
-
1
def signup_topics
-
@assignment_id = params[:id]
-
@sign_up_topics = SignUpTopic.find(:all, :conditions => ['assignment_id = ?', params[:id]])
-
@slots_filled = SignUpTopic.find_slots_filled(params[:id])
-
@slots_waitlisted = SignUpTopic.find_slots_waitlisted(params[:id])
-
@show_actions = true
-
-
-
#find whether assignment is team assignment
-
assignment = Assignment.find(params[:id])
-
#end
-
-
if !assignment.staggered_deadline? and assignment.due_dates.find_by_deadline_type_id(DeadlineType.find_by_name("submission").id).due_at < Time.now
-
@show_actions = false
-
end
-
-
#Find whether the user has signed up for any topics; if so the user won't be able to
-
#sign up again unless the former was a waitlisted topic
-
#if team assignment, then team id needs to be passed as parameter else the user's id
-
if assignment.team_assignment?
-
users_team = SignedUpUser.find_team_users(params[:id],(session[:user].id))
-
-
if users_team.size == 0
-
@selected_topics = nil
-
else
-
#TODO: fix this; cant use 0
-
@selected_topics = otherConfirmedTopicforUser(params[:id], users_team[0].t_id)
-
end
-
else
-
@selected_topics = otherConfirmedTopicforUser(params[:id], session[:user].id)
-
end
-
end
-
-
#This function lets the user choose a particular topic. This function is invoked when the user clicks the green check mark in
-
#the signup sheet
-
1
def signup
-
puts "++++++++++++++++++++++++++++"
-
puts "you called me in signup_controller!"
-
#find the assignment to which user is signing up
-
assignment = Assignment.find(params[:assignment_id])
-
-
if assignment.team_assignment?
-
-
#check whether the user already has a team for this assignment
-
users_team = SignedUpUser.find_team_users(params[:assignment_id],(session[:user].id))
-
-
if users_team.size == 0
-
#if team is not yet created, create new team.
-
team = AssignmentTeam.create_team_and_node(params[:assignment_id])
-
user = User.find(session[:user].id)
-
teamuser = create_team_users(user, team.id)
-
confirmationStatus = confirmTopic(team.id, params[:id], params[:assignment_id])
-
else
-
confirmationStatus = confirmTopic(users_team[0].t_id, params[:id], params[:assignment_id])
-
end
-
else
-
confirmationStatus = confirmTopic(session[:user].id, params[:id], params[:assignment_id])
-
end
-
redirect_to :action => 'signup_topics', :id => params[:assignment_id]
-
end
-
-
# When using this method when creating fields, update race conditions by using db transactions
-
1
def slotAvailable?(topic_id)
-
SignUpTopic.slotAvailable?(topic_id)
-
end
-
#checks for other topics a user may have already signed up for. These include both confirmed as well as waitlisted topics
-
1
def otherConfirmedTopicforUser(assignment_id, creator_id)
-
user_signup = SignedUpUser.find_user_signup_topics(assignment_id,creator_id)
-
user_signup
-
end
-
-
1
def confirmTopic(creator_id, topic_id, assignment_id)
-
#check whether user has signed up already
-
user_signup = otherConfirmedTopicforUser(assignment_id, creator_id)
-
-
sign_up = SignedUpUser.new
-
sign_up.topic_id = params[:id]
-
sign_up.creator_id = creator_id
-
-
result = false
-
if user_signup.size == 0
-
# Using a DB transaction to ensure atomic inserts
-
ActiveRecord::Base.transaction do
-
#check whether slots exist (params[:id] = topic_id) or has the user selected another topic
-
if slotAvailable?(topic_id)
-
sign_up.is_waitlisted = false
-
-
#Update topic_id in participant table with the topic_id
-
participant = Participant.find_by_user_id_and_parent_id(session[:user].id, assignment_id)
-
-
participant.update_topic_id(topic_id)
-
else
-
sign_up.is_waitlisted = true
-
end
-
if sign_up.save
-
result = true
-
end
-
end
-
else
-
#If all the topics choosen by the user are waitlisted,
-
for user_signup_topic in user_signup
-
if user_signup_topic.is_waitlisted == false
-
flash[:error] = "You have already signed up for a topic."
-
return false
-
end
-
end
-
-
# Using a DB transaction to ensure atomic inserts
-
ActiveRecord::Base.transaction do
-
#check whether user is clicking on a topic which is not going to place him in the waitlist
-
if !slotAvailable?(topic_id)
-
sign_up.is_waitlisted = true
-
if sign_up.save
-
result = true
-
end
-
else
-
#if slot exist, then confirm the topic for the user and delete all the waitlist for this user
-
SignUpTopic.cancel_all_waitlists(creator_id, assignment_id)
-
sign_up.is_waitlisted = false
-
sign_up.save
-
-
participant = Participant.find_by_user_id_and_parent_id(session[:user].id, assignment_id)
-
-
participant.update_topic_id(topic_id)
-
participant = Participant.find_by_user_id_and_parent_id(session[:user].id, assignment_id)
-
result = true
-
end
-
end
-
end
-
-
result
-
end
-
-
#This function is used to drop a previously selected topic. This function is invoked when the user clicks the red
-
#cancel mark.
-
-
1
def delete_signup
-
delete_signup_for_topic(params[:assignment_id],params[:id])
-
redirect_to :action => 'signup_topics', :id => params[:assignment_id]
-
end
-
-
#used by delete_signup function above. This functions updates all the database tables when the user drops the topic
-
1
def delete_signup_for_topic(assignment_id,topic_id)
-
#find whether assignment is team assignment
-
assignment = Assignment.find(assignment_id)
-
if SignedUpUser.find_by_creator_id(session[:user].id).nil?
-
puts "we have a problem"
-
end
-
#making sure that the drop date deadline hasn't passed
-
dropDate = DueDate.find(:first, :conditions => {:assignment_id => assignment.id, :deadline_type_id => '6'})
-
if(!dropDate.nil? && dropDate.due_at < Time.now)
-
flash[:error] = "You cannot drop this topic because the drop deadline has passed."
-
else
-
#if team assignment find the creator id from teamusers table and teams
-
if assignment.team_assignment?
-
#users_team will contain the team id of the team to which the user belongs
-
users_team = SignedUpUser.find_team_users(assignment_id,(session[:user].id))
-
signup_record = SignedUpUser.find_by_topic_id_and_creator_id(topic_id, users_team[0].t_id)
-
else
-
signup_record = SignedUpUser.find_by_topic_id_and_creator_id(topic_id, session[:user].id)
-
end
-
-
#if a confirmed slot is deleted then push the first waiting list member to confirmed slot if someone is on the waitlist
-
if signup_record.is_waitlisted == false
-
#find the first wait listed user if exists
-
first_waitlisted_user = SignedUpUser.find_by_topic_id_and_is_waitlisted(topic_id, true)
-
-
if !first_waitlisted_user.nil?
-
# As this user is going to be allocated a confirmed topic, all of his waitlisted topic signups should be purged
-
### Bad policy! Should be changed! (once users are allowed to specify waitlist priorities) -efg
-
first_waitlisted_user.is_waitlisted = false
-
first_waitlisted_user.save
-
-
#update the participants details
-
if assignment.team_assignment?
-
user_id = TeamsUser.find(:first, :conditions => {:team_id => first_waitlisted_user.creator_id}).user_id
-
participant = Participant.find_by_user_id_and_parent_id(user_id,assignment.id)
-
else
-
participant = Participant.find_by_user_id_and_parent_id(first_waitlisted_user.creator_id, assignment.id)
-
end
-
participant.update_topic_id(topic_id)
-
-
SignUpTopic.cancel_all_waitlists(first_waitlisted_user.creator_id,assignment_id)
-
end
-
end
-
-
if !signup_record.nil?
-
participant = Participant.find_by_user_id_and_parent_id(session[:user].id, assignment_id)
-
#update participant's topic id to nil
-
participant.update_topic_id(nil)
-
signup_record.destroy
-
end
-
end #end condition for 'drop deadline' check
-
end
-
end
-
1
class SiteControllersController < ApplicationController
-
-
# GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
-
verify :method => :post, :only => [ :destroy, :create, :update ],
-
1
:redirect_to => { :action => :index }
-
-
1
def index
-
@builtin_site_controllers = SiteController.builtin
-
@app_site_controllers = SiteController.application
-
classify_controllers
-
end
-
-
1
def list
-
redirect_to action: 'index'
-
end
-
-
1
def show
-
@site_controller = SiteController.find(params[:id])
-
@actions = ControllerAction.find(:all,
-
:conditions => ['site_controller_id = ?',
-
params[:id] ],
-
:order => 'name')
-
end
-
-
1
def new
-
foreign
-
@site_controller = SiteController.new(name: params[:id])
-
end
-
-
1
def new_called
-
redirect_to :action => 'new'
-
end
-
-
1
def create
-
@site_controller = SiteController.new(params[:site_controller])
-
if @site_controller.save
-
flash[:notice] = 'SiteController was successfully created.'
-
Role.rebuild_cache
-
redirect_to :action => 'index'
-
else
-
foreign
-
render :action => 'new'
-
end
-
end
-
-
1
def edit
-
@site_controller = SiteController.find(params[:id])
-
foreign
-
end
-
-
1
def update
-
@site_controller = SiteController.find(params[:id])
-
if @site_controller.update_attributes(params[:site_controller])
-
flash[:notice] = 'SiteController was successfully updated.'
-
Role.rebuild_cache
-
redirect_to @site_controller
-
else
-
foreign
-
render :action => 'edit'
-
end
-
end
-
-
1
def destroy
-
SiteController.find(params[:id]).destroy
-
Role.rebuild_cache
-
redirect_to :action => 'index'
-
end
-
-
-
1
protected
-
-
1
def foreign
-
@permissions = Permission.order(:name)
-
end
-
-
# @unknown contains ApplicationController class objects hashed by
-
# name, while @app, @builtin and @missing are arrays of
-
# SiteController ActiveRecord objects.
-
1
def classify_controllers
-
from_classes = SiteController.classes
-
-
from_db = SiteController.order(:name)
-
known = Hash.new
-
@missing = Array.new
-
from_db.each do |dbc|
-
if from_classes.has_key? dbc.name
-
known[dbc.name] = dbc
-
else
-
@missing << dbc
-
end
-
end
-
-
@unknown = Hash.new
-
@app = Array.new
-
@builtin = Array.new
-
-
from_classes.keys.sort.each do |name|
-
if known.has_key? name
-
if known[name].builtin == 1
-
@builtin << known[name]
-
else
-
@app << known[name]
-
end
-
else
-
@unknown[name] = from_classes[name]
-
end
-
end
-
-
@has_missing = (@missing.length > 0) ? true : false
-
@has_unknown = (@unknown.keys.length > 0) ? true : false
-
@has_app = (@app.length > 0) ? true : false
-
@has_builtin = (@builtin.length > 0) ? true : false
-
end
-
-
-
# Given a controller name, returns an array of available actions to
-
# which that controller will respond.
-
-
1
def controller_actions(controller_name)
-
-
controllers = controller_classes()
-
actions = Hash.new()
-
-
if @controller_classes.has_key? controller_name
-
controller = @controller_classes[controller_name]
-
-
for method in controller.public_instance_methods do
-
actions[method] = true
-
end
-
-
for hidden in controller.hidden_actions do
-
actions.delete hidden
-
end
-
end
-
-
return actions.keys
-
end # def controller_actions
-
-
end # class
-
1
class StatisticsController < ApplicationController
-
1
def list_surveys
-
@surveys = SurveyQuestionnaire.all
-
end
-
-
1
def list #list deployments for the survey
-
@survey_id = params[:id]
-
@deployment = SurveyDeployment.find_all_by_course_evaluation_id(@survey_id).map{|u| [u.start_date.to_s+" - "+u.end_date.to_s,u.id] }
-
end
-
1
def view_responses
-
sd_id1=params[:statistics]["survey_deployment_id1"]
-
sd_id2=params[:statistics]["survey_deployment_id2"]
-
-
survey_id1=SurveyDeployment.find(sd_id1).course_evaluation_id
-
@deployment_date1=SurveyDeployment.find(sd_id1).start_date.strftime('%A %B %d %Y, %I:%M%p') + "-" + SurveyDeployment.find(sd_id1).end_date.strftime('%A %B %d %Y, %I:%M%p')
-
@deployment_date2=SurveyDeployment.find(sd_id2).start_date.strftime('%A %B %d %Y, %I:%M%p') + "-" + SurveyDeployment.find(sd_id2).end_date.strftime('%A %B %d %Y, %I:%M%p')
-
-
@survey=Questionnaire.find(survey_id1)
-
@questions=Question.find_all_by_questionnaire_id(survey_id1)
-
-
@num_responses1=Hash.new
-
@num_responses2=Hash.new
-
@t_score=Hash.new
-
@questions.each do |q| # calculate number of responses for each question
-
@num_responses1[q.id]=Hash.new
-
total_question_response=SurveyResponse.find_all_by_survey_deployment_id_and_question_id(sd_id1,q.id).length
-
for i in @survey.min_question_score..@survey.max_question_score
-
if(total_question_response>0)
-
@num_responses1[q.id][i]=(SurveyResponse.find(:all,:conditions=>["survey_deployment_id=? and question_id=? and score=?",sd_id1,q.id,i]).length.to_f/total_question_response)
-
else
-
@num_responses1[q.id][i]=0.0
-
end
-
end
-
-
@num_responses2[q.id]=Hash.new
-
total_question_response=SurveyResponse.find_all_by_survey_deployment_id_and_question_id(sd_id2,q.id).length
-
for i in @survey.min_question_score..@survey.max_question_score
-
if(total_question_response>0)
-
@num_responses2[q.id][i]=(SurveyResponse.find(:all,:conditions=>["survey_deployment_id=? and question_id=? and score=?",sd_id2,q.id,i]).length.to_f/total_question_response)
-
else
-
@num_responses2[q.id][i]=0.0
-
end
-
end
-
#calculate t-test score for the question
-
@t_score[q.id]=t_test(@num_responses1[q.id],@num_responses2[q.id],@survey.min_question_score,@survey.max_question_score)
-
end
-
-
-
end
-
-
1
def t_test(r1,r2,min,max) # The statistical t-test
-
-
-
ex1=exx1=0.0
-
ex2=exx2=0.0
-
-
for i in min..max
-
ex1+=i*r1[i]
-
exx1+=i*i*r1[i]
-
ex2+=i*r2[i]
-
exx2+=i*i*r2[i]
-
end
-
-
logger.info r1
-
logger.info r2
-
logger.info "#{ex1} #{ex2} #{exx1} #{exx2}"
-
-
#Calculate t-test score
-
mean_diff=ex1-ex2
-
s1=exx1-ex1*ex1
-
s2=exx2-ex2*ex2
-
-
if mean_diff==0
-
mean_diff
-
else
-
mean_diff/Math.sqrt(s1/r1.length + s2/r2.length)
-
end
-
-
end
-
-
-
end
-
1
class StudentReviewController < ApplicationController
-
-
1
def list
-
@participant = AssignmentParticipant.find(params[:id])
-
return unless current_user_id?(@participant.user_id)
-
@assignment = @participant.assignment
-
# Find the current phase that the assignment is in.
-
@review_phase = @assignment.get_current_stage(AssignmentParticipant.find(params[:id]).topic_id)
-
#ACS Removed the if condition(and corressponding else) which differentiate assignments as team and individual assignments
-
# to treat all assignments as team assignments
-
@review_mappings = TeamReviewResponseMap.find_all_by_reviewer_id(@participant.id)
-
@metareview_mappings = MetareviewResponseMap.find_all_by_reviewer_id(@participant.id)
-
# Calculate the number of reviews that the user has completed so far.
-
@num_reviews_total = @review_mappings.size
-
@num_reviews_completed = 0
-
@review_mappings.each do |map|
-
@num_reviews_completed += 1 if map.response
-
end
-
@num_reviews_in_progress = @num_reviews_total - @num_reviews_completed
-
# Calculate the number of metareviews that the user has completed so far.
-
@num_metareviews_total = @metareview_mappings.size
-
@num_metareviews_completed = 0
-
@metareview_mappings.each do |map|
-
@num_metareviews_completed += 1 if map.response
-
end
-
@num_metareviews_in_progress = @num_metareviews_total - @num_metareviews_completed
-
if @assignment.staggered_deadline?
-
@review_mappings.each { |review_mapping|
-
#ACS Removed the if condition(and corressponding else) which differentiate assignments as team and individual assignments
-
# to treat all assignments as team assignments
-
participant = AssignmentTeam.get_first_member(review_mapping.reviewee_id)
-
-
if !participant.nil? and !participant.topic_id.nil?
-
review_due_date = TopicDeadline.find_by_topic_id_and_deadline_type_id(participant.topic_id,1)
-
#The logic here is that if the user has at least one reviewee to review then @reviewee_topic_id should
-
#not be nil. Enabling and disabling links to individual reviews are handled at the rhtml
-
if review_due_date.due_at < Time.now
-
@reviewee_topic_id = participant.topic_id
-
end
-
end
-
}
-
review_rounds = @assignment.get_review_rounds
-
deadline_type_id = DeadlineType.find_by_name('review').id
-
-
@metareview_mappings.each do |metareview_mapping|
-
review_mapping = ResponseMap.find_by_id(metareview_mapping.reviewed_object_id)
-
if review_mapping
-
#ACS Removed the if condition(and corressponding else) which differentiate assignments as team and individual assignments
-
# to treat all assignments as team assignments
-
participant = AssignmentTeam.get_first_member(review_mapping.reviewee_id)
-
end
-
if participant && participant.topic_id
-
meta_review_due_date = TopicDeadline.find_by_topic_id_and_deadline_type_id_and_round(participant.topic_id,deadline_type_id,review_rounds)
-
if meta_review_due_date.due_at < Time.now
-
@meta_reviewee_topic_id = participant.topic_id
-
end
-
end
-
end
-
end
-
end
-
-
end
-
1
class StudentTaskController < ApplicationController
-
1
helper :submitted_content
-
-
1
def list
-
redirect_to(:controller => 'eula', :action => 'display') if current_user.is_new_user
-
@student_tasks = StudentTask.from_user current_user
-
-
########Tasks and Notifications##################
-
@tasknotstarted = @student_tasks.select(&:not_started?)
-
@taskrevisions = @student_tasks.select(&:revision?)
-
@notifications = @student_tasks.select(&:notify?)
-
end
-
-
1
def view
-
StudentTask.from_participant_id params[:id]
-
@participant = AssignmentParticipant.find(params[:id])
-
denied unless current_user_id?(@participant.user_id)
-
-
@assignment = @participant.assignment
-
@can_provide_suggestions = @assignment.allow_suggestions
-
#Even if one of the reviewee's work is ready for review "Other's work" link should be active
-
if @assignment.staggered_deadline?
-
review_mappings = @participant.team_reviews
-
-
review_mappings.each do |review_mapping|
-
participant = AssignmentTeam.get_first_member(review_mapping.reviewee_id)
-
-
if participant && participant.topic
-
review_due_date = TopicDeadline.find_by_topic_id_and_deadline_type_id(participant.topic_id, 1)
-
-
if review_due_date.due_at < Time.now && @assignment.get_current_stage(participant.topic_id) != 'Complete'
-
@reviewee_topic_id = participant.topic_id
-
end
-
end
-
end
-
end
-
end
-
-
1
def others_work
-
@participant = AssignmentParticipant.find(params[:id])
-
return unless current_user_id?(@participant.user_id)
-
-
@assignment = @participant.assignment
-
# Finding the current phase that we are in
-
due_dates = DueDate.find(:all, :conditions => ["assignment_id = ?", @assignment.id])
-
@very_last_due_date = DueDate.find(:all, :order => "due_at DESC", :limit =>1, :conditions => ["assignment_id = ?", @assignment.id])
-
next_due_date = @very_last_due_date[0]
-
for due_date in due_dates
-
if due_date.due_at > Time.now
-
if due_date.due_at < next_due_date.due_at
-
next_due_date = due_date
-
end
-
end
-
end
-
-
@review_phase = next_due_date.deadline_type_id;
-
if next_due_date.review_of_review_allowed_id == DueDate::LATE or next_due_date.review_of_review_allowed_id == DueDate::OK
-
if @review_phase == DeadlineType.find_by_name("metareview").id
-
@can_view_metareview = true
-
end
-
end
-
-
@review_mappings = ResponseMap.find_all_by_reviewer_id(@participant.id)
-
@review_of_review_mappings = MetareviewResponseMap.find_all_by_reviewer_id(@participant.id)
-
end
-
-
1
def your_work
-
-
end
-
end
-
1
class StudentTeamController < ApplicationController
-
1
auto_complete_for :user, :name
-
-
1
def view
-
@student = AssignmentParticipant.find(params[:id])
-
return unless current_user_id?(@student.user_id)
-
-
@send_invs = Invitation.find(:all, :conditions => ['from_id = ? and assignment_id = ?', @student.user.id, @student.assignment.id])
-
@received_invs = Invitation.find(:all, :conditions => ['to_id = ? and assignment_id = ? and reply_status = "W"', @student.user.id, @student.assignment.id])
-
end
-
-
1
def create
-
@student = AssignmentParticipant.find(params[:id])
-
return unless current_user_id?(@student.user_id)
-
-
check = AssignmentTeam.find(:all, :conditions => ["name =? and parent_id =?", params[:team][:name], @student.parent_id])
-
-
#check if the team name is in use
-
if (check.length == 0)
-
@team = AssignmentTeam.new(params[:team])
-
@team.parent_id = @student.parent_id
-
@team.save
-
parent = AssignmentNode.find_by_node_object_id(@student.parent_id)
-
TeamNode.create(:parent_id => parent.id, :node_object_id => @team.id)
-
user = User.find(@student.user_id)
-
@team.add_member(user, @team.parent_id)
-
redirect_to :controller => 'student_team', :action => 'view' , :id=> @student.id
-
else
-
flash[:notice] = 'Team name is already in use.'
-
redirect_to :controller => 'student_team', :action => 'view' , :id=> @student.id
-
end
-
end
-
-
1
def edit
-
@team = AssignmentTeam.find_by_id(params[:team_id])
-
@student = AssignmentParticipant.find(params[:student_id])
-
return unless current_user_id?(@student.user_id)
-
end
-
-
1
def update
-
@team = AssignmentTeam.find_by_id(params[:team_id])
-
check = AssignmentTeam.find(:all, :conditions => ["name =? and parent_id =?", params[:team][:name], @team.parent_id])
-
if (check.length == 0)
-
if @team.update_attributes(params[:team])
-
redirect_to :controller => 'student_team', :action => 'view', :id => params[:student_id]
-
end
-
elsif (check.length == 1 && (check[0].name <=> @team.name) == 0)
-
redirect_to :controller => 'student_team', :action => 'view', :id => params[:student_id]
-
else
-
flash[:notice] = 'Team name is already in use.'
-
redirect_to :controller =>'student_team', :action => 'edit', :team_id =>params[:team_id], :student_id => params[:student_id]
-
end
-
end
-
-
1
def advertise_for_partners
-
puts "team #{params[:team_id]}"
-
Team.update_all("advertise_for_partner=true",:id=>params[:team_id])
-
#respond_to do |format|
-
# format.html # index.html.erb
-
#format.xml { render :xml => @log_entries }
-
#end
-
#redirect_to :controller => 'student_team', :action => 'advertise_for_partners' , :id => params[:team_id]
-
end
-
1
def remove
-
Team.update_all("advertise_for_partner=false",:id=>params[:team_id])
-
redirect_to :controller => 'student_team', :action => 'view' , :id => params[:team_id]
-
end
-
-
1
def leave
-
@student = AssignmentParticipant.find(params[:student_id])
-
return unless current_user_id?(@student.user_id)
-
#remove the topic_id from participants
-
@student.update_topic_id(nil)
-
-
#remove the entry from teams_users
-
user = TeamsUser.find(:first, :conditions =>["team_id =? and user_id =?", params[:team_id], @student.user_id])
-
if user
-
user.destroy
-
end
-
-
#if your old team does not have any members, delete the entry for the team
-
other_members = TeamsUser.find(:all, :conditions => ['team_id = ?', params[:team_id]])
-
if other_members.length == 0
-
old_team = AssignmentTeam.find(:first, :conditions => ['id = ?', params[:team_id]])
-
if old_team != nil
-
old_team.destroy
-
#if assignment has signup sheet then the topic selected by the team has to go back to the pool
-
#or to the first team in the waitlist
-
signups = SignedUpUser.find(:all, :conditions => {:creator_id => params[:team_id]})
-
signups.each {|signup|
-
#get the topic_id
-
signup_topic_id = signup.topic_id
-
#destroy the signup
-
signup.destroy
-
-
#get the number of non-waitlisted users signed up for this topic
-
non_waitlisted_users = SignedUpUser.find(:all, :conditions => {:topic_id => signup_topic_id, :is_waitlisted => false})
-
#get the number of max-choosers for the topic
-
max_choosers = SignUpTopic.find(:first, :conditions => {:id => signup_topic_id}).max_choosers
-
-
#check if this number is less than the max choosers
-
if non_waitlisted_users.length < max_choosers
-
first_waitlisted_user = SignedUpUser.find(:first, :conditions => {:topic_id => signup_topic_id, :is_waitlisted => true})
-
-
#moving the waitlisted user into the confirmed signed up users list
-
if !first_waitlisted_user.nil?
-
first_waitlisted_user.is_waitlisted = false
-
first_waitlisted_user.save
-
-
waitlisted_team_user = TeamsUser.find(:first, :conditions => {:team_id => first_waitlisted_user.creator_id})
-
#waitlisted_team_user could be nil since the team the student left could have been the one waitlisted on the topic
-
#and teams_users for the team has been deleted in one of the earlier lines of code
-
-
if !waitlisted_team_user.nil?
-
user_id = waitlisted_team_user.user_id
-
if !user_id.nil?
-
participant = Participant.find_by_user_id(user_id)
-
participant.update_topic_id(nil)
-
end
-
end
-
end
-
end
-
#signup.destroy
-
}
-
end
-
end
-
-
#remove all the sent invitations
-
old_invs = Invitation.find(:all, :conditions => ['from_id = ? and assignment_id = ?', @student.user_id, @student.parent_id])
-
for old_inv in old_invs
-
old_inv.destroy
-
end
-
-
#reset the participants submission directory to nil
-
#per EFG:
-
#the participant is responsible for resubmitting their work
-
#no restriction is placed on when a participant can leave
-
@student.directory_num = nil
-
@student.save
-
-
redirect_to :controller => 'student_team', :action => 'view' , :id => @student.id
-
end
-
-
1
def review
-
@assignment = Assignment.find_by_id(params[:assignment_id])
-
redirect_to :controller =>'questionnaire', :action => 'view_questionnaire', :id => @assignment.questionnaires.find_by_type('AuthorFeedbackQuestionnaire').id
-
end
-
end
-
1
require 'zip/zip'
-
-
1
class SubmittedContentController < ApplicationController
-
1
helper :wiki
-
-
1
def edit
-
@participant = AssignmentParticipant.find(params[:id])
-
return unless current_user_id?(@participant.user_id)
-
-
@assignment = @participant.assignment
-
-
#ACS We have to check if the number of members on the team is more than 1(group assignment)
-
#hence use team count for the check
-
if @assignment.max_team_size > 1 && @participant.team.nil?
-
flash[:alert] = "This is a team assignment. Before submitting your work, you must <a style='color: blue;' href='../../student_team/view/#{params[:id]}'>create a team</a>, even if you will be the only member of the team"
-
redirect_to :controller => 'student_task', :action => 'view', :id => params[:id]
-
else if @participant.team.nil?
-
#create a new team for current user before submission
-
team = AssignmentTeam.create_team_and_node(@assignment.id)
-
puts "+++++@participant.user_id = "+ @participant.user_id.to_s
-
puts "+++++@assignment.id = "+ @assignment.id.to_s
-
team.add_member(User.find(@participant.user_id),@assignment.id)
-
puts "+++++++++ I just create a new team!"
-
end
-
end
-
end
-
-
1
def view
-
@participant = AssignmentParticipant.find(params[:id])
-
return unless current_user_id?(@participant.user_id)
-
-
@assignment = @participant.assignment
-
end
-
-
1
def submit_hyperlink
-
participant = AssignmentParticipant.find(params[:id])
-
return unless current_user_id?(participant.user_id)
-
-
begin
-
participant.submmit_hyperlink(params['submission'])
-
participant.update_resubmit_times
-
rescue
-
flash[:error] = "The URL or URI is not valid. Reason: "+$!
-
end
-
redirect_to :action => 'edit', :id => participant.id
-
end
-
-
# Note: This is not used yet in the view until we all decide to do so
-
1
def remove_hyperlink
-
participant = AssignmentParticipant.find(params[:id])
-
return unless current_user_id?(participant.user_id)
-
-
begin
-
participant.remove_hyperlink(params['chk_links'].to_i)
-
rescue
-
flash[:error] = $!
-
end
-
redirect_to :action => 'edit', :id => participant.id
-
end
-
-
1
def submit_file
-
participant = AssignmentParticipant.find(params[:id])
-
return unless current_user_id?(participant.user_id)
-
-
file = params[:uploaded_file]
-
participant.set_student_directory_num
-
-
@current_folder = DisplayOption.new
-
@current_folder.name = "/"
-
if params[:current_folder]
-
@current_folder.name = FileHelper::sanitize_folder(params[:current_folder][:name])
-
end
-
-
curr_directory = participant.get_path.to_s+@current_folder.name
-
-
-
if !File.exists? curr_directory
-
FileUtils.mkdir_p(curr_directory)
-
end
-
-
safe_filename = file.original_filename.gsub(/\\/,"/")
-
safe_filename = FileHelper::sanitize_filename(safe_filename) # new code to sanitize file path before upload*
-
full_filename = curr_directory + File.split(safe_filename).last.gsub(" ",'_') #safe_filename #curr_directory +
-
File.open(full_filename, "wb") { |f| f.write(file.read) }
-
if params['unzip']
-
SubmittedContentHelper::unzip_file(full_filename, curr_directory, true) if get_file_type(safe_filename) == "zip"
-
end
-
participant.update_resubmit_times
-
-
#send message to reviewers when submission has been updated
-
participant.assignment.email(participant.id) rescue nil # If the user has no team: 1) there are no reviewers to notify; 2) calling email will throw an exception. So rescue and ignore it.
-
-
redirect_to :action => 'edit', :id => participant.id
-
end
-
-
-
1
def folder_action
-
@participant = AssignmentParticipant.find(params[:id])
-
return unless current_user_id?(@participant.user_id)
-
-
@current_folder = DisplayOption.new
-
@current_folder.name = "/"
-
if params[:current_folder]
-
@current_folder.name = FileHelper::sanitize_folder(params[:current_folder][:name])
-
end
-
if params[:faction][:delete]
-
delete_selected_files
-
elsif params[:faction][:rename]
-
rename_selected_file
-
elsif params[:faction][:move]
-
move_selected_file
-
elsif params[:faction][:copy]
-
copy_selected_file
-
elsif params[:faction][:create]
-
create_new_folder
-
end
-
-
redirect_to :action => 'edit', :id => @participant.id
-
end
-
-
1
def download
-
#folder_name = FileHelper::sanitize_folder(@current_folder.name)
-
folder_name = params['current_folder']['name']
-
# -- This code removed on 4/10/09 ... was breaking downloads of files with hyphens in them ...file_name = FileHelper::sanitize_filename(params['download'])
-
file_name = params['download']
-
-
file_split = file_name.split('.')
-
if file_split.length > 1 and (file_split[1] == 'htm' or file_split[1] == 'html')
-
send_file(folder_name+ "/" + file_name, :type => Mime::HTML.to_s, :disposition => 'inline')
-
else
-
if !File.directory?(folder_name + "/" + file_name)
-
file_ext = File.extname(file_name)[1..-1]
-
file_ext = 'bin' if file_ext.blank? # default to application/octet-stream
-
send_file folder_name + "/" + file_name,
-
:disposition => 'inline',
-
:type => Mime::Type.lookup_by_extension(file_ext)
-
else
-
raise "Directory downloads are not supported"
-
end
-
end
-
end
-
-
# This was written for a custom rubric used by Dr. Jennifer Kidd (ODU)
-
# Note that the file that is being uploaded here is a REVIEW, not submitted work.
-
1
def custom_submit_file
-
-
begin
-
file = params[:uploaded_file]
-
participant = Participant.find(params[:participant_id])
-
-
@current_folder = DisplayOption.new
-
@current_folder.name = "/"
-
if params[:current_folder]
-
@current_folder.name = FileHelper::sanitize_folder(params[:current_folder][:name])
-
end
-
-
curr_directory = participant.assignment.get_path.to_s+ "/" +params[:map].to_s + @current_folder.name
-
if !File.exists? curr_directory
-
FileUtils.mkdir_p(curr_directory)
-
else
-
FileUtils.rm_rf(curr_directory)
-
FileUtils.mkdir_p(curr_directory)
-
end
-
-
safe_filename = file.original_filename.gsub(/\\/,"/")
-
safe_filename = FileHelper::sanitize_filename(safe_filename) # new code to sanitize file path before upload*
-
full_filename = curr_directory + File.split(safe_filename).last.gsub(" ",'_') #safe_filename #curr_directory +
-
File.open(full_filename, "wb") { |f| f.write(file.read) }
-
rescue
-
end
-
-
if params[:return_to] == "edit"
-
redirect_to :controller=>'response', :action => params[:return_to], :id => params[:id]
-
else
-
redirect_to :controller=>'response', :action => params[:return_to], :id => params[:map]
-
end
-
end
-
-
1
private
-
-
1
def get_file_type file_name
-
base = File.basename(file_name)
-
if base.split(".").size > 1
-
return base.split(".")[base.split(".").size-1]
-
end
-
end
-
-
-
1
def move_selected_file
-
old_filename = params[:directories][params[:chk_files]] + "/" + params[:filenames][params[:chk_files]]
-
newloc = @participant.get_path
-
newloc += "/"
-
newloc += params[:faction][:move]
-
begin
-
FileHelper::move_file(old_filename, newloc)
-
flash[:note] = "The file was moved successfully from \"/#{params[:filenames][params[:chk_files]]}\" to \"/#{params[:faction][:move]}\""
-
rescue
-
flash[:error] = "There was a problem moving the file: "+$!
-
end
-
end
-
-
1
def rename_selected_file
-
old_filename = params[:directories][params[:chk_files]] +"/"+ params[:filenames][params[:chk_files]]
-
new_filename = params[:directories][params[:chk_files]] +"/"+ FileHelper::sanitize_filename(params[:faction][:rename])
-
begin
-
if !File.exist?(new_filename)
-
File.send("rename", old_filename, new_filename)
-
else
-
raise "A file already exists in this directory with the name \"#{params[:faction][:rename]}\""
-
end
-
rescue
-
flash[:error] = "There was a problem renaming the file: "+$!
-
end
-
end
-
-
1
def delete_selected_files
-
filename = params[:directories][params[:chk_files]] +"/"+ params[:filenames][params[:chk_files]]
-
FileUtils.rm_r(filename)
-
end
-
-
1
def copy_selected_file
-
old_filename = params[:directories][params[:chk_files]] +"/"+ params[:filenames][params[:chk_files]]
-
new_filename = params[:directories][params[:chk_files]] +"/"+ FileHelper::sanitize_filename(params[:faction][:copy])
-
begin
-
if File.exist?(new_filename)
-
raise "A file with this name already exists. Please delete the existing file before copying."
-
end
-
-
if File.exist?(old_filename)
-
FileUtils.cp_r(old_filename, new_filename)
-
else
-
raise "The referenced file does not exist."
-
end
-
rescue
-
flash[:error] = "There was a problem copying the file: "+$!
-
end
-
end
-
-
1
def create_new_folder
-
newloc = @participant.get_path
-
newloc += "/"
-
newloc += params[:faction][:create]
-
begin
-
FileHelper::create_directory_from_path(newloc)
-
flash[:note] = "The directory #{params[:faction][:create]} was created."
-
rescue
-
flash[:error] = $!
-
end
-
end
-
end
-
1
class SuggestionController < ApplicationController
-
-
1
def add_comment
-
@suggestioncomment = SuggestionComment.new(params[:suggestion_comment])
-
@suggestioncomment.suggestion_id=params[:id]
-
@suggestioncomment.commenter= session[:user].name
-
if @suggestioncomment.save
-
flash[:notice] = "Successfully added your comment"
-
else
-
flash[:error] = "Error while adding comment"
-
end
-
redirect_to :action => "show", :id => params[:id]
-
end
-
# GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
-
verify :method => :post, :only => [ :destroy, :create, :update ],
-
1
:redirect_to => { :action => :list }
-
-
1
def list
-
@suggestions = Suggestion.find_all_by_assignment_id(params[:id])
-
@assignment = Assignment.find(params[:id])
-
end
-
-
1
def show
-
@suggestion = Suggestion.find(params[:id])
-
end
-
-
1
def new
-
@suggestion = Suggestion.new
-
session[:assignment_id] = params[:id]
-
end
-
-
1
def create
-
@suggestion = Suggestion.new(params[:suggestion])
-
@suggestion.assignment_id = session[:assignment_id]
-
@suggestion.status = 'Initiated'
-
if params[:suggestion_anonymous].nil?
-
@suggestion.unityID = session[:user].name
-
else
-
@suggestion.unityID = "";
-
end
-
-
if @suggestion.save
-
render :action => 'confirm_save'
-
else
-
render :action => 'new'
-
end
-
end
-
-
1
def confirm_save
-
# Action to display successful creation of suggestion
-
end
-
-
1
def submit
-
if !params[:add_comment].nil?
-
add_comment
-
elsif !params[:approve_suggestion].nil?
-
approve_suggestion
-
elsif !params[:reject_suggestion].nil?
-
reject_suggestion
-
end
-
end
-
-
1
def approve_suggestion
-
@suggestion = Suggestion.find(params[:id])
-
@signuptopic = SignUpTopic.new
-
@signuptopic.topic_identifier = 'S' + @suggestion.id.to_s
-
@signuptopic.topic_name = @suggestion.title
-
@signuptopic.assignment_id = @suggestion.assignment_id
-
@signuptopic.max_choosers = 3;
-
-
if @signuptopic.save && @suggestion.update_attribute('status', 'Approved')
-
flash[:notice] = 'Successfully approved the suggestion.'
-
else
-
flash[:error] = 'Error when approving the suggestion.'
-
end
-
redirect_to :action => 'show', :id => @suggestion
-
end
-
-
1
def reject_suggestion
-
@suggestion = Suggestion.find(params[:id])
-
-
if @suggestion.update_attribute('status', 'Rejected')
-
flash[:notice] = 'Successfully rejected the suggestion'
-
else
-
flash[:error] = 'Error when rejecting the suggestion'
-
end
-
redirect_to :action => 'show', :id => @suggestion
-
end
-
end
-
1
class SurveyController < ApplicationController
-
-
1
def assign
-
@assignment = Assignment.find(params[:id])
-
@assigned_surveys = SurveyHelper::get_assigned_surveys(@assignment.id)
-
@surveys = Array.new
-
-
if params['subset'] == "mine"
-
@surveys = Questionnaire.find(:all, :conditions => ["type_id = 2 and instructor_id = ?", session[:user].id])
-
elsif params['subset'] == "public"
-
@surveys = Questionnaire.find(:all, :conditions => ["type_id = 2 and private = 0"])
-
else
-
@surveys = @assigned_surveys
-
end
-
-
if params['update']
-
if params[:surveys]
-
@checked = params[:surveys]
-
-
if params['submit_subset'] == "mine"
-
@submit_surveys = Questionnaire.find(:all, :conditions => ["type_id = 2 and instructor_id = ?", session[:user].id])
-
elsif params['submit_subset'] == "public"
-
@submit_surveys = Questionnaire.find(:all, :conditions => ["type_id = 2 and private = 0"])
-
else
-
@submit_surveys = @assigned_surveys
-
end
-
-
for survey in @submit_surveys
-
unless @checked.include? survey.id
-
AssignmentQuestionnaire.delete_all(["questionnaire_id = ? and assignment_id = ?", survey.id, @assignment.id])
-
@assigned_surveys.delete(survey)
-
end
-
end
-
-
for checked_survey in @checked
-
@current = Questionnaire.find(checked_survey)
-
unless @assigned_surveys.include? @current
-
@new = AssignmentQuestionnaire.new(:questionnaire_id => checked_survey, :assignment_id => @assignment.id)
-
@new.save
-
@assigned_surveys << @current
-
end
-
end
-
else
-
for survey in @submit_surveys
-
AssignmentQuestionnaire.delete_all(["questionnaire_id = ? and assignment_id = ?", survey.id, @assignment.id])
-
@assigned_surveys.delete(survey)
-
@surveys.delete(survey)
-
end
-
end
-
end
-
@surveys.sort!{|a,b| a.name <=> b.name}
-
end
-
-
-
-
end
-
-
1
class SurveyDeploymentController < ApplicationController
-
-
1
def new
-
@surveys=Questionnaire.find_all_by_type('CourseEvaluationQuestionnaire').map{|u| [u.name, u.id] }
-
@course = Course.find_all_by_instructor_id(session[:user].id).map{|u| [u.name, u.id] }
-
@total_students = CourseParticipant.find_all_by_parent_id(@course[0][1]).count
-
end
-
-
1
def create
-
survey_deployment=params[:survey_deployment]
-
-
@survey_deployment=SurveyDeployment.new(survey_deployment)
-
if(params[:random_subset]["value"]=="1")
-
@survey_deployment.num_of_students=User.find_all_by_role_id(Role.student.id).length * rand
-
end
-
-
if(@survey_deployment.save)
-
add_participants(@survey_deployment.num_of_students,@survey_deployment.id)
-
redirect_to :action=>'list'
-
else
-
@surveys=Questionnaire.find_all_by_type('CourseEvaluationQuestionnaire').map{|u| [u.name, u.id] }
-
@course = Course.find_all_by_instructor_id(session[:user].id).map{|u| [u.name, u.id] }
-
@total_students = CourseParticipant.find_all_by_parent_id(@course[0][1]).count
-
render(:action=>'new')
-
end
-
end
-
-
1
def list
-
@survey_deployments=SurveyDeployment.find(:all)
-
@surveys={}
-
@survey_deployments.each do |sd|
-
@surveys[sd.id]=Questionnaire.find(sd.course_evaluation_id).name
-
end
-
end
-
-
-
-
1
def delete
-
SurveyDeployment.find(params[:id]).destroy
-
SurveyParticipant.find_all_by_survey_deployment_id(params[:id]).each do |sp|
-
sp.destroy
-
end
-
SurveyResponse.find_all_by_survey_deployment_id(params[:id]).each do |sr|
-
sr.destroy
-
end
-
redirect_to :action=>'list'
-
end
-
-
1
def add_participants(num_of_participants,survey_deployment_id) #Add participants
-
users=User.find_all_by_role_id(Role.student.id)
-
users_rand=users.sort_by{rand} #randomize user list
-
num_of_participants.times do |i|
-
survey_participant=SurveyParticipant.new
-
survey_participant.user_id=users_rand[i].id
-
survey_participant.survey_deployment_id=survey_deployment_id
-
survey_participant.save
-
end
-
-
end
-
-
1
def reminder_thread
-
-
#Check status of reminder thread
-
@reminder_thread_status="Running"
-
unless MiddleMan.get_worker(session[:reminder_key])
-
@reminder_thread_status="Not Running"
-
end
-
-
end
-
-
1
def toggle_reminder_thread
-
#Create reminder thread using BackgroundRb or kill it if its already running
-
unless MiddleMan.get_worker(session[:reminder_key])
-
session[:reminder_key]=MiddleMan.new_worker :class=>:reminder_worker, :args=>{:num_reminders=>3} # 3 reminders for now
-
else
-
MiddleMan.delete_worker(session[:reminder_key])
-
session[:reminder_key]=nil
-
end
-
redirect_to :action=>'reminder_thread'
-
end
-
-
-
-
end
-
1
class SurveyResponseController < ApplicationController
-
-
1
def begin_survey
-
unless session[:user] #redirect to homepage if user not logged in
-
redirect_to '/'
-
return
-
end
-
-
@participants = AssignmentParticipant.find(:all, :conditions => ["user_id = ? and parent_id = ?", session[:user].id, params[:id]])
-
if @participants.length == 0 #make sure the user is a participant of the assignment
-
redirect_to '/'
-
return
-
end
-
end
-
-
1
def create
-
-
if params[:course_eval] #Check if its a course evaluation
-
@assigned_surveys = Questionnaire.find_all(params[:id])
-
@survey = Questionnaire.find(params[:questionnaire_id])
-
@questions = @survey.questions
-
@course_eval=params[:course_eval]
-
#@assigned_surveys = SurveyHelper::get_course_surveys(params[:course_id], 1)
-
return
-
end
-
-
unless session[:user] && session[:assignment_id] #redirect to homepage if user not logged in or session not tied to assignment
-
redirect_to '/'
-
return
-
end
-
-
begin
-
@assignment = Assignment.find(params[:id])
-
@assigned_surveys = SurveyHelper::get_all_available_surveys(@assignment.id, 1)
-
-
if params[:submit]
-
@submit_survey = Questionnaire.find(params[:survey_id])
-
@submit_questions = @submit_survey.questions
-
@scores = params[:score]
-
@comments = params[:comments]
-
for question in @submit_questions
-
list = []
-
list = SurveyResponse.find(:all, :conditions => ["assignment_id = ? and survey_id = ? and question_id = ? and email = ?", params[:id], params[:survey_id], question.id, params[:email]]) if params[:email]
-
if list.length > 0
-
@new = list[0]
-
else
-
@new = SurveyResponse.new
-
end
-
@new.survey_id = params[:survey_id]
-
@new.question_id = question.id
-
@new.assignment_id = params[:id]
-
@new.email = params[:email]
-
@new.score = @scores[question.id.to_s]
-
@new.comments = @comments[question.id.to_s]
-
@new.save
-
end
-
end
-
-
# if params[:count].to_i == @assigned_surveys.length
-
# redirect_to(:action =>'submit', :survey_id=>params[:survey_id], :score=>@scores, :assignment_id=>params[:id])
-
# return
-
# end
-
-
@survey = @assigned_surveys[params[:count].to_i]
-
@questions = @survey.questions
-
rescue
-
redirect_to '/'
-
return
-
end
-
end
-
-
1
def submit
-
@submitted = true;
-
@survey_id = params[:survey_id]
-
@survey = Questionnaire.find(@survey_id)
-
@questions = @survey.questions
-
@scores = params[:score]
-
@comments = params[:comments]
-
@assignment_id = params[:assignment_id]
-
for question in @questions
-
@new = SurveyResponse.new
-
@new.survey_id = @survey_id
-
@new.question_id = question.id
-
@new.assignment_id = @assignment_id
-
@new.survey_deployment_id=params[:survey_deployment_id]
-
@new.email = params[:email]
-
@new.score = @scores[question.id.to_s]
-
@new.comments = @comments[question.id.to_s]
-
@new.save
-
end
-
-
if !params[:survey_deployment_id]
-
@surveys = SurveyHelper::get_assigned_surveys(@assignment_id)
-
end
-
end
-
-
1
def view_responses
-
-
if params[:course_eval] # Check if this is a course evaluation
-
survey_id=SurveyDeployment.find(params[:id]).course_evaluation_id
-
@surveys = Questionnaire.find(:all, :conditions=>["id=?", survey_id])
-
#Temprorary Assignment object
-
@assignment=Assignment.new
-
@assignment.name="Course Evaluation"
-
@assignment.id=params[:id]
-
@course_eval=params[:course_eval]
-
else
-
@assignment = Assignment.find(params[:id])
-
@surveys = SurveyHelper::get_all_available_surveys(params[:id], session[:user].role_id)
-
end
-
@responses = Array.new
-
@empty = true
-
for survey in @surveys
-
min = survey.min_question_score
-
max = survey.max_question_score
-
this_response_survey = Hash.new
-
this_response_survey[:name] = survey.name
-
this_response_survey[:id] = survey.id
-
this_response_survey[:questions] = Array.new
-
this_response_survey[:empty] = true
-
this_response_survey[:avg_labels] = Array.new
-
this_response_survey[:avg_values] = Array.new
-
this_response_survey[:max] = max
-
if !params[:course_eval]
-
surveylist = SurveyResponse.find(:all, :conditions => ["assignment_id = ? and survey_id = ?", params[:id], survey.id])
-
else
-
surveylist = SurveyResponse.find(:all, :conditions => ["survey_deployment_id = ? and survey_id = ?", params[:id], survey.id])
-
end
-
if surveylist.length > 0
-
@empty = false
-
this_response_survey[:empty] = false
-
end
-
for question in survey.questions
-
this_response_question = Hash.new
-
this_response_question[:name] = question.txt
-
this_response_question[:id] = question.id
-
this_response_question[:labels] = Array.new
-
this_response_question[:values] = Array.new
-
this_response_question[:count] = 0
-
this_response_question[:average] = 0
-
for i in min..max
-
if !question.true_false? || i == min || i == max
-
if !params[:course_eval]
-
list = SurveyResponse.find(:all, :conditions => ["assignment_id = ? and survey_id = ? and question_id = ? and score = ?", params[:id], survey.id, question.id, i])
-
elsif params[:course_eval]
-
list = SurveyResponse.find(:all, :conditions => ["survey_deployment_id = ? and survey_id = ? and question_id = ? and score = ?", params[:id], survey.id, question.id, i]);
-
end
-
if question.true_false?
-
if i == min
-
this_response_question[:labels] << "False"
-
else
-
this_response_question[:labels] << "True"
-
end
-
else
-
this_response_question[:labels] << i
-
end
-
this_response_question[:values] << list.length.to_s
-
this_response_question[:average] += i*list.length
-
end
-
end
-
if !params[:course_eval]
-
no_of_question = SurveyResponse.find(:all, :conditions => ["assignment_id = ? and survey_id = ? and question_id = ?", params[:id], survey.id, question.id])
-
else
-
no_of_question = SurveyResponse.find(:all, :conditions => ["survey_deployment_id = ? and survey_id = ? and question_id = ?", params[:id], survey.id, question.id])
-
end
-
this_response_question[:count] = no_of_question.length
-
-
if this_response_question[:count] > 0
-
@empty = false
-
this_response_survey[:empty] = false
-
this_response_question[:average] /= this_response_question[:count].to_f
-
this_response_survey[:avg_labels] << this_response_question[:name][0..50]
-
this_response_survey[:avg_values] << this_response_question[:average]
-
end
-
this_response_survey[:questions] << this_response_question
-
end
-
@responses << this_response_survey
-
end
-
end
-
-
1
def comments
-
unless params[:course_eval] # Check if survey is a course evaluation
-
@responses = SurveyResponse.find(:all, :conditions => ["assignment_id = ? and survey_id = ? and question_id = ?", params[:assignment_id], params[:survey_id], params[:question_id]], :order => "score");
-
else
-
@responses = SurveyResponse.find(:all, :conditions => ["survey_deployment_id = ? and survey_id = ? and question_id = ?", params[:assignment_id], params[:survey_id], params[:question_id]], :order => "score");
-
@course_eval="1"
-
end
-
-
@question = Question.find(params[:question_id])
-
@survey = Questionnaire.find(params[:survey_id])
-
-
unless params[:course_eval]
-
@assignment = Assignment.find(params[:assignment_id])
-
else
-
@assignment=Assignment.new
-
@assignment.name="Course Evaluation"
-
end
-
-
end
-
end
-
1
class SystemSettingsController < ApplicationController
-
1
def index
-
list
-
render :action => 'list'
-
end
-
-
# GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
-
verify :method => :post, :only => [ :destroy, :create, :update ],
-
1
:redirect_to => { :action => :list }
-
-
1
def list
-
@system_settings = SystemSettings.find(:first)
-
redirect_to :action => :show, :id => @system_settings
-
-
# @system_settings_pages, @system_settings = paginate :system_settings,
-
# :class_name => 'SystemSettings', :per_page => 10
-
end
-
-
1
def show
-
foreign()
-
@system_settings = SystemSettings.find(:first)
-
end
-
-
1
def new
-
@system_settings = SystemSettings.find(:first)
-
if @system_settings != nil
-
redirect_to :action => :edit, :id => @system_settings.id
-
else
-
foreign()
-
@system_settings = SystemSettings.new
-
end
-
end
-
-
1
def create
-
@system_settings = SystemSettings.new(params[:system_settings])
-
if @system_settings.save
-
flash[:notice] = 'SystemSettings was successfully created.'
-
redirect_to :action => 'list'
-
else
-
render :action => 'new'
-
end
-
end
-
-
1
def edit
-
foreign()
-
@system_settings = SystemSettings.find(params[:id])
-
end
-
-
1
def update
-
@system_settings = SystemSettings.find(params[:id])
-
if @system_settings.update_attributes(params[:system_settings])
-
flash[:notice] = 'SystemSettings was successfully updated.'
-
redirect_to :action => 'show', :id => @system_settings
-
else
-
render :action => 'edit'
-
end
-
end
-
-
1
def destroy
-
SystemSettings.find(params[:id]).destroy
-
redirect_to :action => 'list'
-
end
-
-
1
protected
-
-
1
def foreign
-
@roles = Role.find(:all, :order => 'name')
-
@pages = ContentPage.find(:all, :order => 'name')
-
@markup_styles = MarkupStyle.find(:all, :order => 'name')
-
@markup_styles.unshift MarkupStyle.new(:id => nil, :name => '(none)')
-
end
-
-
end
-
1
class TeamController < ApplicationController
-
1
auto_complete_for :user, :name
-
-
1
def create_teams_view
-
@parent = Object.const_get(session[:team_type]).find(params[:id])
-
end
-
-
1
def delete_all
-
parent = Object.const_get(session[:team_type]).find(params[:id])
-
Team.delete_all_by_parent(parent)
-
redirect_to :action => 'list', :id => parent.id
-
end
-
-
1
def create_teams
-
parent = Object.const_get(session[:team_type]).find(params[:id])
-
Team.randomize_all_by_parent(parent, session[:team_type], params[:team][:size].to_i)
-
-
redirect_to :action => 'list', :id => parent.id
-
end
-
-
1
def list
-
if params[:type]
-
session[:team_type] = params[:type]
-
end
-
-
@root_node = Object.const_get(session[:team_type] + "Node").find_by_node_object_id(params[:id])
-
@child_nodes = @root_node.get_teams()
-
end
-
-
1
def new
-
@parent = Object.const_get(session[:team_type]).find(params[:id])
-
end
-
-
1
def create
-
parent = Object.const_get(session[:team_type]).find(params[:id])
-
begin
-
Team.check_for_existing(parent, params[:team][:name], session[:team_type])
-
team = Object.const_get(session[:team_type]+'Team').create(:name => params[:team][:name], :parent_id => parent.id)
-
TeamNode.create(:parent_id => parent.id, :node_object_id => team.id)
-
redirect_to :action => 'list', :id => parent.id
-
rescue TeamExistsError
-
flash[:error] = $!
-
redirect_to :action => 'new', :id => parent.id
-
end
-
end
-
-
1
def update
-
team = Team.find(params[:id])
-
parent = Object.const_get(session[:team_type]).find(team.parent_id)
-
begin
-
Team.check_for_existing(parent, params[:team][:name], session[:team_type])
-
-
team.name = params[:team][:name]
-
team.save
-
redirect_to :action => 'list', :id => parent.id
-
rescue TeamExistsError
-
flash[:error] = $!
-
redirect_to :action => 'edit', :id => team.id
-
end
-
end
-
-
1
def edit
-
@team = Team.find(params[:id])
-
end
-
-
1
def delete
-
team = Team.find(params[:id])
-
course = Object.const_get(session[:team_type]).find(team.parent_id)
-
team.delete
-
redirect_to :action => 'list', :id => course.id
-
end
-
-
# Copies existing teams from a course down to an assignment
-
# The team and team members are all copied.
-
1
def inherit
-
assignment = Assignment.find(params[:id])
-
if assignment.course_id >= 0
-
course = Course.find(assignment.course_id)
-
teams = course.get_teams
-
if teams.length > 0
-
teams.each{
-
|team|
-
team.copy(assignment.id)
-
}
-
else
-
flash[:note] = "No teams were found to inherit."
-
end
-
else
-
flash[:error] = "No course was found for this assignment."
-
end
-
redirect_to :controller => 'team', :action => 'list', :id => assignment.id
-
end
-
-
# Copies existing teams from an assignment up to a course
-
# The team and team members are all copied.
-
1
def bequeath
-
team = AssignmentTeam.find(params[:id])
-
assignment = Assignment.find(team.parent_id)
-
if assignment.course_id >= 0
-
course = Course.find(assignment.course_id)
-
team.copy(course.id)
-
flash[:note] = "\""+team.name+"\" was successfully copied to \""+course.name+"\""
-
else
-
flash[:error] = "This assignment is not #{url_for(:controller => 'assignment', :action => 'assign', :id => assignment.id)} with a course."
-
end
-
redirect_to :controller => 'team', :action => 'list', :id => assignment.id
-
end
-
end
-
1
class TeamsParticipantsController < ApplicationController
-
-
1
def auto_complete_for_user_name
-
team = Team.find(session[:team_id])
-
@users = team.get_possible_team_members(params[:user][:name])
-
render :inline => "<%= auto_complete_result @users, 'name' %>", :layout => false
-
end
-
-
1
def list
-
@team = Team.find_by_id(params[:id])
-
@assignment = Assignment.find(@team.assignment_id)
-
@teams_participants = TeamsParticipant.paginate(:page => params[:page], :per_page => 10, :conditions => ["team_id = ?", params[:id]])
-
end
-
-
1
def new
-
@team = Team.find_by_id(params[:id])
-
end
-
-
1
def create
-
user = User.find_by_name(params[:user][:name].strip)
-
if !user
-
urlCreate = url_for :controller => 'users', :action => 'new'
-
flash[:error] = "\"#{params[:user][:name].strip}\" is not defined. Please <a href=\"#{urlCreate}\">create</a> this user before continuing."
-
end
-
team = Team.find_by_id(params[:id])
-
-
team.add_member(user, team.parent_id)
-
-
# flash[:error] = $!
-
#end
-
redirect_to :controller => 'team', :action => 'list', :id => team.parent_id
-
end
-
-
1
def delete
-
teamuser = TeamsParticipant.find(params[:id])
-
parent_id = Team.find(teamuser.team_id).parent_id
-
teamuser.destroy
-
redirect_to :controller => 'team', :action => 'list', :id => parent_id
-
end
-
-
1
def delete_selected
-
params[:item].each {
-
|item_id|
-
team_user = TeamsParticipant.find(item_id).first
-
team_user.destroy
-
}
-
-
redirect_to :action => 'list', :id => params[:id]
-
end
-
-
end
-
1
class TeamsUsersController < ApplicationController
-
-
1
def auto_complete_for_user_name
-
team = Team.find(session[:team_id])
-
@users = team.get_possible_team_members(params[:user][:name])
-
render :inline => "<%= auto_complete_result @users, 'name' %>", :layout => false
-
end
-
-
1
def list
-
@team = Team.find_by_id(params[:id])
-
@assignment = Assignment.find(@team.assignment_id)
-
@teams_users = TeamsUser.paginate(:page => params[:page], :per_page => 10, :conditions => ["team_id = ?", params[:id]])
-
end
-
-
1
def new
-
@team = Team.find_by_id(params[:id])
-
end
-
-
1
def create
-
user = User.find_by_name(params[:user][:name].strip)
-
if !user
-
urlCreate = url_for :controller => 'users', :action => 'new'
-
flash[:error] = "\"#{params[:user][:name].strip}\" is not defined. Please <a href=\"#{urlCreate}\">create</a> this user before continuing."
-
end
-
team = Team.find_by_id(params[:id])
-
-
add_member_return=team.add_member(user, team.parent_id)
-
if add_member_return==false
-
flash[:error]= "The team already has the maximum number of members."
-
end
-
-
# flash[:error] = $!
-
#end
-
redirect_to :controller => 'team', :action => 'list', :id => team.parent_id
-
end
-
-
1
def delete
-
teamuser = TeamsUser.find(params[:id])
-
parent_id = Team.find(teamuser.team_id).parent_id
-
teamuser.destroy
-
redirect_to :controller => 'team', :action => 'list', :id => parent_id
-
end
-
-
1
def delete_selected
-
params[:item].each {
-
|item_id|
-
team_user = TeamsUser.find(item_id).first
-
team_user.destroy
-
}
-
-
redirect_to :action => 'list', :id => params[:id]
-
end
-
-
end
-
1
class TreeDisplayController < ApplicationController
-
1
helper :application
-
-
# direct access to questionnaires
-
1
def goto_questionnaires
-
node_object = TreeFolder.find_by_name('Questionnaires')
-
session[:root] = FolderNode.find_by_node_object_id(node_object.id).id
-
redirect_to :controller => 'tree_display', :action => 'list'
-
end
-
-
# direct access to review rubrics
-
1
def goto_review_rubrics
-
1
node_object = TreeFolder.find_by_name('Review')
-
1
session[:root] = FolderNode.find_by_node_object_id(node_object.id).id
-
1
redirect_to :controller => 'tree_display', :action => 'list'
-
end
-
-
# direct access to metareview rubrics
-
1
def goto_metareview_rubrics
-
node_object = TreeFolder.find_by_name('Metareview')
-
session[:root] = FolderNode.find_by_node_object_id(node_object.id).id
-
redirect_to :controller => 'tree_display', :action => 'list'
-
end
-
-
# direct access to teammate review rubrics
-
1
def goto_teammatereview_rubrics
-
node_object = TreeFolder.find_by_name('Teammate Review')
-
session[:root] = FolderNode.find_by_node_object_id(node_object.id).id
-
redirect_to :controller => 'tree_display', :action => 'list'
-
end
-
-
# direct access to author feedbacks
-
1
def goto_author_feedbacks
-
node_object = TreeFolder.find_by_name('Author Feedback')
-
session[:root] = FolderNode.find_by_node_object_id(node_object.id).id
-
redirect_to :controller => 'tree_display', :action => 'list'
-
end
-
-
# direct access to global survey
-
1
def goto_global_survey
-
node_object = TreeFolder.find_by_name('Global Survey')
-
session[:root] = FolderNode.find_by_node_object_id(node_object.id).id
-
redirect_to :controller => 'tree_display', :action => 'list'
-
end
-
-
# direct access to surveys
-
1
def goto_surveys
-
node_object = TreeFolder.find_by_name('Survey')
-
session[:root] = FolderNode.find_by_node_object_id(node_object.id).id
-
redirect_to :controller => 'tree_display', :action => 'list'
-
end
-
-
# direct access to course evaluations
-
1
def goto_course_evaluations
-
node_object = TreeFolder.find_by_name('Course Evaluation')
-
session[:root] = FolderNode.find_by_node_object_id(node_object.id).id
-
redirect_to :controller => 'tree_display', :action => 'list'
-
end
-
-
# direct access to courses
-
1
def goto_courses
-
node_object = TreeFolder.find_by_name('Courses')
-
session[:root] = FolderNode.find_by_node_object_id(node_object.id).id
-
redirect_to :controller => 'tree_display', :action => 'list'
-
end
-
-
# direct access to assignments
-
1
def goto_assignments
-
node_object = TreeFolder.find_by_name('Assignments')
-
session[:root] = FolderNode.find_by_node_object_id(node_object.id).id
-
redirect_to :controller => 'tree_display', :action => 'list'
-
end
-
-
# called when the display is requested
-
# ajbudlon, July 3rd 2008
-
1
def list
-
14
display = params[:display] || session[:display]
-
14
if display
-
@sortvar = display[:sortvar]
-
@sortorder = display[:sortorder]
-
if display[:check] == "1"
-
@show = nil
-
else
-
@show = true
-
end
-
else
-
14
@show = true
-
end
-
-
14
@sortvar ||= 'created_at'
-
14
@sortorder ||= 'desc'
-
-
14
if session[:root]
-
1
@root_node = Node.find(session[:root])
-
1
@child_nodes = @root_node.get_children(@sortvar,@sortorder,session[:user].id,@show)
-
else
-
13
@child_nodes = FolderNode.get()
-
end
-
end
-
-
1
def drill
-
12
session[:root] = params[:root]
-
12
redirect_to :controller => 'tree_display', :action => 'list'
-
end
-
end
-
1
class UsersController < ApplicationController
-
1
auto_complete_for :user, :name
-
# GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
-
verify :method => :post, :only => [ :destroy, :create, :update ],
-
1
:redirect_to => { :action => :list }
-
-
1
def index
-
if (current_user_role? == "Student")
-
redirect_to(:action => AuthHelper::get_home_action(session[:user]), :controller => AuthHelper::get_home_controller(session[:user]))
-
else
-
list
-
render :action => 'list'
-
end
-
end
-
-
1
def self.participants_in(assignment_id)
-
users = Array.new
-
participants = AssignmentParticipant.find_by_parent_id(assignment_id)
-
participants.each{
-
|participant|
-
users << User.find(participant.user_id)
-
}
-
end
-
-
1
def auto_complete_for_user_name
-
user = session[:user]
-
role = Role.find(user.role_id)
-
@users = User.find(:all, :conditions => ['name LIKE ? and (role_id in (?) or id = ?)', "#{params[:user][:name]}%",role.get_available_roles, user.id])
-
render :inline => "<%= auto_complete_result @users, 'name' %>", :layout => false
-
end
-
-
#for displaying the list of users
-
1
def list
-
user = session[:user]
-
role = Role.find(user.role_id)
-
all_users = User.find(:all, :order => 'name', :conditions => ['role_id in (?) or id = ?', role.get_available_roles, user.id])
-
-
letter = params[:letter]
-
session[:letter] = letter
-
if letter == nil
-
letter = all_users.first.name[0,1].downcase
-
end
-
logger.info "#{letter}"
-
@letters = Array.new
-
-
@per_page = 1
-
-
# Check if the "Show" button for pagination is clicked
-
# If yes, set @per_page to the value of the selection dropdown
-
# Else, if the request is from one of the letter links on the top
-
# set @per_page to 1 (25 names per page).
-
# Else, set @per_page to the :num_users param passed in from
-
# the will_paginate method from the 'pagination' partial.
-
if params[:paginate_show]
-
@per_page = params[:num_users]
-
elsif params[:from_letter]
-
@per_page = 1
-
else
-
@per_page = params[:num_users]
-
end
-
-
# Get the users list to show on current page
-
@users = paginate_list(role, user.id, letter)
-
-
all_users.each {
-
| userObj |
-
first = userObj.name[0,1].downcase
-
if not @letters.include?(first)
-
@letters << first
-
end
-
}
-
end
-
-
1
def show_selection
-
@user = User.find_by_name(params[:user][:name])
-
if @user != nil
-
get_role
-
if @role.parent_id == nil || @role.parent_id < (session[:user]).role_id || @user.id == (session[:user]).id
-
render :action => 'show'
-
else
-
flash[:note] = 'The specified user is not available for editing.'
-
redirect_to :action => 'list'
-
end
-
else
-
flash[:note] = params[:user][:name]+' does not exist.'
-
redirect_to :action => 'list'
-
end
-
end
-
-
1
def show
-
if (params[:id].nil?) || ((current_user_role? == "Student") && (session[:user].id != params[:id].to_i))
-
redirect_to(:action => AuthHelper::get_home_action(session[:user]), :controller => AuthHelper::get_home_controller(session[:user]))
-
else
-
@user = User.find(params[:id])
-
get_role
-
end
-
end
-
-
1
def new
-
@user = User.new
-
foreign
-
end
-
-
1
def create
-
-
# if the user name already exists, register the user by email address
-
check = User.find_by_name(params[:user][:name])
-
if check != nil
-
params[:user][:name] = params[:user][:email]
-
end
-
-
@user = User.new(params[:user])
-
# record the person who created this new user
-
@user.parent_id = (session[:user]).id
-
# set the user's timezone to its parent's
-
@user.timezonepref = User.find(@user.parent_id).timezonepref
-
-
if @user.save
-
#Instructor and Administrator users need to have a default set for their notifications
-
# the creation of an AssignmentQuestionnaire object with only the User ID field populated
-
# ensures that these users have a default value of 15% for notifications.
-
#TAs and Students do not need a default. TAs inherit the default from the instructor,
-
# Students do not have any checks for this information.
-
if @user.role.name == "Instructor" or @user.role.name == "Administrator"
-
AssignmentQuestionnaire.create(:user_id => @user.id)
-
end
-
flash[:notice] = 'User was successfully created.'
-
redirect_to :action => 'list'
-
else
-
foreign
-
render :action => 'new'
-
end
-
end
-
-
-
1
def edit
-
@user = User.find(params[:id])
-
get_role
-
foreign
-
end
-
-
1
def update
-
@user = User.find params[:id]
-
-
if @user.update_attributes params[:user]
-
flash[:notice] = 'User was successfully updated.'
-
redirect_to @user
-
else
-
foreign
-
render :action => 'edit'
-
end
-
end
-
-
-
1
def destroy
-
begin
-
user = User.find(params[:id])
-
AssignmentParticipant.find_all_by_user_id(user.id).each{|participant| participant.delete}
-
TeamsUser.find_all_by_user_id(user.id).each{|teamuser| teamuser.delete}
-
AssignmentQuestionnaire.find_all_by_user_id(user.id).each{|aq| aq.destroy}
-
user.destroy
-
rescue
-
flash[:error] = $!
-
end
-
-
redirect_to :action => 'list'
-
end
-
-
1
def keys
-
if (params[:id].nil?) || ((current_user_role? == "Student") && (session[:user].id != params[:id].to_i))
-
redirect_to(:action => AuthHelper::get_home_action(session[:user]), :controller => AuthHelper::get_home_controller(session[:user]))
-
else
-
@user = User.find(params[:id])
-
@private_key = @user.generate_keys
-
end
-
end
-
-
1
protected
-
-
1
def foreign
-
role = Role.find((session[:user]).role_id)
-
@all_roles = Role.find(:all, :conditions => ['id in (?) or id = ?',role.get_available_roles,role.id])
-
end
-
-
1
private
-
-
1
def get_role
-
if @user && @user.role_id
-
@role = Role.find(@user.role_id)
-
elsif @user
-
@role = Role.new(:id => nil, :name => '(none)')
-
end
-
end
-
-
# For filtering the users list with proper search and pagination.
-
1
def paginate_list(role, user_id, letter)
-
paginate_options = {"1" => 25, "2" => 50, "3" => 100}
-
-
# If the above hash does not have a value for the key,
-
# it means that we need to show all the users on the page
-
#
-
# Just a point to remember, when we use pagination, the
-
# 'users' variable should be an object, not an array
-
-
#The type of condition for the search depends on what the user has selected from the search_by dropdown
-
condition = "(role_id in (?) or id = ?) and name like ?" #default used when clicking on letters
-
search_filter = letter + '%'
-
@search_by = params[:search_by]
-
if @search_by == '1' #search by user name
-
condition = "(role_id in (?) or id = ?) and name like ?"
-
search_filter = '%' + letter + '%'
-
elsif @search_by == '2' # search by full name
-
condition = "(role_id in (?) or id = ?) and fullname like ?"
-
search_filter = '%' + letter + '%'
-
elsif @search_by == '3' # search by email
-
condition = "(role_id in (?) or id = ?) and email like ?"
-
search_filter = '%' + letter + '%'
-
end
-
-
if (paginate_options["#{@per_page}"].nil?) #displaying all - no pagination
-
users = User.paginate(:page => params[:page], :order => 'name', :per_page => User.count(:all), :conditions => [condition, role.get_available_roles, user_id, search_filter])
-
else #some pagination is active - use the per_page
-
users = User.paginate(:page => params[:page], :order => 'name', :per_page => paginate_options["#{@per_page}"], :conditions => [condition, role.get_available_roles, user_id, search_filter])
-
end
-
users
-
end
-
end
-
1
class WaitlistsController < ApplicationController
-
1
def index
-
list
-
render :action => 'list'
-
end
-
-
# GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
-
verify :method => :post, :only => [ :destroy, :create, :update ],
-
1
:redirect_to => { :action => :list }
-
-
1
def list
-
@waitlists = Waitlist.paginate(:page => params[:page], :per_page => 10)
-
end
-
-
1
def show
-
@waitlist = Waitlist.find(params[:id])
-
end
-
-
1
def new
-
@waitlist = Waitlist.new
-
end
-
-
1
def create
-
@waitlist = Waitlist.new(params[:waitlist])
-
if @waitlist.save
-
flash[:notice] = 'Waitlist was successfully created.'
-
redirect_to :action => 'list'
-
else
-
render :action => 'new'
-
end
-
end
-
-
1
def edit
-
@waitlist = Waitlist.find(params[:id])
-
end
-
-
1
def update
-
@waitlist = Waitlist.find(params[:id])
-
if @waitlist.update_attributes(params[:waitlist])
-
flash[:notice] = 'Waitlist was successfully updated.'
-
redirect_to :action => 'show', :id => @waitlist
-
else
-
render :action => 'edit'
-
end
-
end
-
-
1
def destroy
-
Waitlist.find(params[:id]).destroy
-
redirect_to :action => 'list'
-
end
-
end
-
#these 4 helpers consist of the list of plot options that are available for the graph type
-
1
module LineGraphHelper
-
#development note
-
# 1)method for generate the data packet has already been - completed: helpers/chart.rb
-
# 2)javascript for rendering the chart - partially completed
-
# currently value x axis can not be independently set
-
# 3)data mining method for gathering data - partially completed
-
# there's always more to add
-
end
-
-
1
module BarChartHelper
-
-
end
-
-
1
module PieChartHelper
-
#only for single object compaireson meaning
-
# 1)method for generate the data packet has already been - completed: helpers/chart.rb
-
# 2)javascript for rendering the chart - completed
-
-
# good for showing grade distributions
-
# methods needed to convert the data gathered to useful way of displaying
-
end
-
-
1
module ScatterPlotHelper
-
# 1)method for generate the data packet has already been - completed: helpers/chart.rb
-
# 2)javascript for rendering the chart - completed
-
-
-
end
-
-
1
module AnalyticHelper
-
#====== generating chart data ================#
-
1
def bar_chart_data(object_type, object_id_list, data_type_list)
-
data_point = Array.new
-
object_model = Object.const_get(object_type.capitalize)
-
object_id_list.each do |object_id|
-
object = object_model.find(object_id)
-
object_data = Hash.new
-
object_data[:name] = object.name
-
object_data[:data] = gather_data(object, data_type_list)
-
data_point << object_data
-
end
-
option = Hash.new
-
option[:x_axis_categories] =data_type_list
-
Chart.new(:bar, data_point, option).data
-
end
-
-
1
def gather_data(object, data_type_array)
-
data_array = Array.new
-
data_type_array.each do |data_method|
-
data_array << object.send(data_method)
-
end
-
data_array
-
end
-
-
#======== sorting ============#
-
1
def sort_by_name(array_of_arrays)
-
array_of_arrays.sort {|x,y| x[0] <=> y[0]}
-
end
-
-
#======= helper data formatting =====#
-
#TODO: implementing normalize for bar chart
-
1
def normalize(array)
-
normalized_array = Array.new
-
max = array.max
-
array.each do |element|
-
normalized_array << element.to_f/max
-
end
-
normalized_array
-
end
-
-
1
def distribution(array, num_intervals, x_min = array.min)
-
distribution = Array.new
-
interval_size = ((array.max - x_min).to_f/num_intervals).ceil
-
intervals = (1..num_intervals).to_a.collect { |val| val*interval_size }
-
intervals.each do |interval_max|
-
distribution << array.select { |a| a < interval_max }.count
-
array.reject! { |a| a < interval_max }
-
-
end
-
distribution
-
end
-
-
1
def distribution_categories(array, num_intervals, x_min = array.min)
-
categories = Array.new
-
interval_size = ((array.max - x_min).to_f/num_intervals).ceil
-
intervals = (1..num_intervals).to_a.collect { |val| val*interval_size }
-
interval_min = 0
-
intervals.each do |interval_max|
-
categories << (interval_min..interval_max).to_s
-
interval_min = interval_max
-
end
-
categories
-
end
-
end
-
# Methods added to this helper will be available to all templates in the application.
-
1
module ApplicationHelper
-
1
def is_available(user, owner_id)
-
user.id == owner_id ||
-
36
user.admin? ||
-
user.super_admin?
-
end
-
-
# Make a new user of the same class
-
1
def self.get_user_role(l_user)
-
eval "#{l_user.role.name.gsub(/-/, '')}.new"
-
end
-
-
1
def self.get_user_first_name(recipient)
-
8
recipient.first_name
-
end
-
-
1
def get_field(element, field)
-
element.send field
-
end
-
-
1
def flash_message(type)
-
220
if flash[type]
-
1
"<div class='flash_#{type.to_s}'>#{flash[type]}</div>".html_safe
-
end
-
end
-
end
-
1
module AssignmentHelper
-
-
1
def course_options(instructor)
-
courses = Course.find_all_by_instructor_id(instructor.id)
-
options = Array.new
-
options << ['-----------', nil]
-
courses.each do |course|
-
options << [course.name, course.id]
-
end
-
options
-
end
-
-
1
def wiki_type_options
-
wiki_type_options = Array.new
-
WikiType.all.each do |wiki_type|
-
if wiki_type.name == 'No'
-
wiki_type_options << ['------', wiki_type.id]
-
else
-
wiki_type_options << [wiki_type.name, wiki_type.id]
-
end
-
end
-
wiki_type_options
-
end
-
-
1
def questionnaire_options(assignment, type)
-
questionnaires = Questionnaire.find(:all, :conditions => ['private = 0 or instructor_id = ?', assignment.instructor_id], :order => 'name')
-
options = Array.new
-
questionnaires.select { |x| x.type == type }.each do |questionnaire|
-
options << [questionnaire.name, questionnaire.id]
-
end
-
options
-
end
-
-
1
def review_strategy_options
-
review_strategy_options = Array.new
-
Assignment::REVIEW_STRATEGIES.each do |strategy|
-
review_strategy_options << [strategy.to_s, strategy.to_s]
-
end
-
review_strategy_options
-
end
-
-
1
def deadline_rights_options
-
permissions = DeadlineRight.all
-
options = Array.new
-
permissions.each do |permission|
-
options << [permission.name, permission.id]
-
end
-
options
-
end
-
-
#retrive or create a due_date
-
# use in views/assignment/edit.html.erb
-
1
def due_date(assignment, type, round = 0)
-
-
-
due_dates = assignment.find_due_dates(type)
-
if type == 'submission'
-
due_dates += assignment.find_due_dates('resubmission')
-
elsif type == 'review'
-
due_dates += assignment.find_due_dates('rereview')
-
end
-
-
due_dates.delete_if { |due_date| due_date.due_at.nil? }
-
due_dates.sort! { |x, y| x.due_at <=> y.due_at }
-
-
if due_dates[round].nil? or round < 0
-
due_date = DueDate.new
-
due_date.deadline_type = DeadlineType.find_by_name(type)
-
#creating new round
-
#TODO: add code to assign default permission to the newly created due_date according to the due_date type
-
due_date.submission_allowed_id = DueDate.default_permission(type, 'submission_allowed')
-
due_date.review_allowed_id = DueDate.default_permission(type, 'review_allowed')
-
due_date.review_of_review_allowed_id = DueDate.default_permission(type, 'review_of_review_allowed')
-
due_date
-
else
-
due_dates[round]
-
end
-
end
-
-
-
1
def questionnaire(assignment, type)
-
questionnaire = assignment.questionnaires.find_by_type(type)
-
if questionnaire.nil?
-
questionnaire = Object.const_get(type).new
-
questionnaire
-
else
-
questionnaire
-
end
-
end
-
-
1
def assignment_questionnaire(assignment, type)
-
questionnaire = assignment.questionnaires.find_by_type(type)
-
-
if questionnaire.nil?
-
default_weight = Hash.new
-
default_weight['ReviewQuestionnaire'] = 100
-
default_weight['MetareviewQuestionnaire'] = 0
-
default_weight['AuthorFeedbackQuestionnaire'] = 0
-
default_weight['TeammateReviewQuestionnaire'] = 0
-
-
default_aq = AssignmentQuestionnaire.find_by_user_id_and_assignment_id_and_questionnaire_id(assignment.instructor_id, nil, nil)
-
if default_aq.nil?
-
default_limit = 15
-
else
-
default_limit = default_aq.notification_limit
-
end
-
-
aq = AssignmentQuestionnaire.new
-
aq.questionnaire_weight = default_weight[type]
-
aq.notification_limit = default_limit
-
aq.assignment = @assignment
-
aq
-
else
-
assignment.assignment_questionnaires.find_by_questionnaire_id(questionnaire.id)
-
end
-
end
-
-
-
end
-
1
module AuthHelper
-
1
def self.get_home_action(user)
-
11
user.role.try(:get_home_action)
-
rescue
-
11
'drill'
-
end
-
-
1
def self.get_home_controller(user)
-
11
user.role.try(:get_home_controller)
-
rescue
-
11
'tree_display'
-
end
-
end
-
#TODO: rename to ChartDataPacket
-
#TODO: find a fitting place for this file maybe in module
-
1
class Chart
-
1
@@chart_index = 0
-
1
@@header = false
-
1
attr :chart_id
-
1
attr :width
-
1
attr :data
-
-
1
def initialize(type,data,option=nil,width = nil)
-
@@chart_index = @@chart_index + 1
-
chart_data = self.class.dataAdapter(type,data,option);
-
unless width.nil?
-
@width = width
-
end
-
@data = chart_data
-
@chart_id = @@chart_index
-
end
-
-
1
def get_id_str()
-
"chart_container_" + @chart_id.to_s
-
end
-
-
1
def self.include_header?()
-
!@@header
-
end
-
-
1
def self.set_header()
-
@@header = true
-
end
-
-
1
def self.dataAdapter(type,data,optionalConf)
-
template = data_template[type];
-
if (type == :pie) then
-
data[:type] = 'pie';
-
template[:series] = [data]
-
else
-
template[:series] = data
-
end
-
if optionalConf.nil? then
-
template[:title][:text] = ""
-
template.delete(:subtitle)
-
template.delete(:yAxis)
-
template.delete(:xAxis)
-
else
-
if template[:subtitle].nil? then
-
template[:subtitle]={}
-
end
-
if optionalConf[:title].nil? then
-
template[:title][:text] = ""
-
else
-
template[:title][:text] = optionalConf[:title]
-
end
-
if optionalConf[:subtitle].nil? then
-
template.delete(:subtitle)
-
else
-
template[:subtitle][:text]=optionalConf[:subtitle]
-
end
-
-
if optionalConf[:y_axis].nil? then
-
template.delete(:yAxis)
-
else
-
template[:yAxis][:title][:text]=optionalConf[:y_axis]
-
end
-
-
if optionalConf[:x_axis].nil? then
-
template[:xAxis].delete(:title)
-
else
-
template[:xAxis][:title][:text] = optionalConf[:x_axis]
-
end
-
-
if optionalConf[:x_axis_categories].nil? then
-
template[:xAxis].delete(:categories)
-
else
-
template[:xAxis][:categories]=optionalConf[:x_axis_categories]
-
end
-
end
-
template
-
end
-
-
-
1
def self.data_template()
-
{
-
:pie => {
-
:chart => {
-
:plotBackgroundColor => nil,
-
:plotBorderWidth => nil,
-
:plotShadow => false
-
},
-
:title => {
-
:text => 'Title'
-
},
-
:subtitle => {
-
:text => 'Title'
-
},
-
:xAxis => {},
-
:yAxis => {},
-
:tooltip => {
-
:pointFormat => '{series.name}: <b>{point.percentage}%</b>',
-
:percentageDecimals => 1
-
},
-
:plotOptions => {
-
:pie => {
-
:allowPointSelect => true,
-
:cursor => 'pointer',
-
:dataLabels => {
-
:enabled => true,
-
:color => '#000000',
-
:connectorColor => '#000000',
-
:format => "<b>{point.name}</b>: {percentage:.2f} %"
-
}
-
}
-
},
-
:series => [
-
{
-
:type => 'pie',
-
:name => 'XXX pie',
-
:data => [
-
['part 1',45.0],
-
['part 2',26.8],
-
['part 3',8.5],
-
['part 4',6.2],
-
['part 5',0.7]
-
]
-
}
-
]
-
},
-
:bar => {
-
:chart => {
-
:type => 'column'
-
},
-
:title => {:text => "Review score for XXXX"},
-
:subtitle => {:text => "subtitle here"},
-
:xAxis => {
-
:title =>{},
-
:categories => [ 'Problem1', 'Problem2', 'Problem3', 'Problem4', 'Problem5', 'Problem6', 'Problem7', 'Problem8', 'Problem9', 'Problem10', 'Problem11','Problem12']
-
},
-
:yAxis => {
-
:min => 0,
-
:title => {
-
:text => 'score'
-
}
-
},
-
:tooltip => {
-
:headerFormat => '<span style="font-size:10px">{point.key}</span><table>',
-
:pointFormat => '<tr><td style="color:{series.color};padding:0">{series.name}: </td>' +'<td style="padding:0"><b>{point.y:.1f}</b></td></tr>',
-
:footerFormat => '</table>',
-
:shared => true,
-
:useHTML => true
-
},
-
:plotOptions => {
-
:column => {
-
:pointPadding => 0.2,
-
:borderWidth => 0
-
}
-
},
-
:series => [
-
{
-
:name => 'review 1',
-
:data => [9.9, 7.5, 6.4, 9.2, 4.0, 6.0, 5.6, 8.5, 6.4, 4.1, 5.6, 4.4]
-
}, {
-
:name => 'review 2',
-
:data => [3.6, 8.8, 8.5, 3.4, 6.0, 4.5, 5.0, 4.3, 9.2, 8.5, 6.6, 9.3]
-
}, {
-
:name => 'review 3',
-
:data => [8.9, 8.8, 9.3, 4.4, 7.0, 8.3, 9.0, 9.6, 5.4, 6.2, 9.3, 5.2]
-
}
-
]
-
},
-
-
:line => {
-
:title => {:text => "Review score for XXXX"},
-
:subtitle => {:text => "subtitle here"},
-
:xAxis => {
-
:title =>{},
-
:categories => [ 'Problem1', 'Problem2', 'Problem3', 'Problem4', 'Problem5', 'Problem6', 'Problem7', 'Problem8', 'Problem9', 'Problem10', 'Problem11','Problem12']
-
},
-
:yAxis => {
-
:min => 0,
-
:title => {
-
:text => 'score'
-
}
-
},
-
:tooltip => {
-
:headerFormat => '<span style="font-size:10px">{point.key}</span><table>',
-
:pointFormat => '<tr><td style="color:{series.color};padding:0">{series.name}: </td>' +'<td style="padding:0"><b>{point.y:.1f} mm</b></td></tr>',
-
:footerFormat => '</table>',
-
:shared => true,
-
:useHTML => true
-
},
-
:plotOptions => {
-
:column => {
-
:pointPadding => 0.2,
-
:borderWidth => 0
-
}
-
},
-
:series => [
-
{
-
:name => 'review 1',
-
:data => [9.9, 7.5, 6.4, 9.2, 4.0, 6.0, 5.6, 8.5, 6.4, 4.1, 5.6, 4.4]
-
}, {
-
:name => 'review 2',
-
:data => [3.6, 8.8, 8.5, 3.4, 6.0, 4.5, 5.0, 4.3, 9.2, 8.5, 6.6, 9.3]
-
}, {
-
:name => 'review 3',
-
:data => [8.9, 8.8, 9.3, 4.4, 7.0, 8.3, 9.0, 9.6, 5.4, 6.2, 9.3, 5.2]
-
}
-
]
-
},
-
-
:scatter => {
-
:chart => {
-
:type => 'scatter',
-
:zoomType => 'xy'
-
},
-
:title => {
-
:text => 'Height Versus Weight of 507 Individuals by Gender'
-
},
-
:subtitle => {
-
:text => 'Source: Heinz 2003'
-
},
-
:xAxis => {
-
:title => {
-
:enabled => true,
-
:text => 'Height (cm)'
-
},
-
:startOnTick => true,
-
:endOnTick => true,
-
:showLastLabel => true
-
},
-
:yAxis => {
-
:title => {
-
:text => 'Weight (kg)'
-
}
-
},
-
:legend => {
-
:layout => 'vertical',
-
:align => 'left',
-
:verticalAlign => 'top',
-
:x => 100,
-
:y => 70,
-
:floating => true,
-
:backgroundColor => '#FFFFFF',
-
:borderWidth => 1
-
},
-
:plotOptions => {
-
:scatter => {
-
:marker => {
-
:radius => 5,
-
:states => {
-
:hover => {
-
:enabled => true,
-
:lineColor => 'rgb(100,100,100)'
-
}
-
}
-
},
-
:states => {
-
:hover => {
-
:marker => {
-
:enabled => false
-
}
-
}
-
},
-
:tooltip => {
-
:headerFormat => '<b>{series.name}</b><br>',
-
:pointFormat => '{point.x} cm, {point.y} kg'
-
}
-
}
-
},
-
:series => [
-
{
-
:name => 'Female',
-
:color => 'rgba(223, 83, 83, .5)',
-
:data => [[161.2, 51.6], [167.5, 59.0], [159.5, 49.2], [157.0, 63.0], [155.8, 53.6],
-
[170.0, 59.0], [159.1, 47.6], [166.0, 69.8], [176.2, 66.8], [160.2, 75.2],
-
[172.5, 55.2], [170.9, 54.2], [172.9, 62.5], [153.4, 42.0], [160.0, 50.0],
-
[147.2, 49.8], [168.2, 49.2], [175.0, 73.2], [157.0, 47.8], [167.6, 68.8],
-
[159.5, 50.6], [175.0, 82.5], [166.8, 57.2], [176.5, 87.8], [170.2, 72.8],
-
[174.0, 54.5], [173.0, 59.8], [179.9, 67.3], [170.5, 67.8], [160.0, 47.0],
-
[154.4, 46.2], [162.0, 55.0], [176.5, 83.0], [160.0, 54.4], [152.0, 45.8],
-
[162.1, 53.6], [170.0, 73.2], [160.2, 52.1], [161.3, 67.9], [166.4, 56.6],
-
[168.9, 62.3], [163.8, 58.5], [167.6, 54.5], [160.0, 50.2], [161.3, 60.3],
-
[167.6, 58.3], [165.1, 56.2], [160.0, 50.2], [170.0, 72.9], [157.5, 59.8],
-
[167.6, 61.0], [160.7, 69.1], [163.2, 55.9], [152.4, 46.5], [157.5, 54.3],
-
[168.3, 54.8], [180.3, 60.7], [165.5, 60.0], [165.0, 62.0], [164.5, 60.3],
-
[156.0, 52.7], [160.0, 74.3], [163.0, 62.0], [165.7, 73.1], [161.0, 80.0],
-
[162.0, 54.7], [166.0, 53.2], [174.0, 75.7], [172.7, 61.1], [167.6, 55.7],
-
[151.1, 48.7], [164.5, 52.3], [163.5, 50.0], [152.0, 59.3], [169.0, 62.5],
-
[164.0, 55.7], [161.2, 54.8], [155.0, 45.9], [170.0, 70.6], [176.2, 67.2],
-
[170.0, 69.4], [162.5, 58.2], [170.3, 64.8], [164.1, 71.6], [169.5, 52.8],
-
[163.2, 59.8], [154.5, 49.0], [159.8, 50.0], [173.2, 69.2], [170.0, 55.9],
-
[161.4, 63.4], [169.0, 58.2], [166.2, 58.6], [159.4, 45.7], [162.5, 52.2],
-
[159.0, 48.6], [162.8, 57.8], [159.0, 55.6], [179.8, 66.8], [162.9, 59.4],
-
[161.0, 53.6], [151.1, 73.2], [168.2, 53.4], [168.9, 69.0], [173.2, 58.4],
-
[171.8, 56.2], [178.0, 70.6], [164.3, 59.8], [163.0, 72.0], [168.5, 65.2],
-
[166.8, 56.6], [172.7, 105.2], [163.5, 51.8], [169.4, 63.4], [167.8, 59.0],
-
[159.5, 47.6], [167.6, 63.0], [161.2, 55.2], [160.0, 45.0], [163.2, 54.0],
-
[162.2, 50.2], [161.3, 60.2], [149.5, 44.8], [157.5, 58.8], [163.2, 56.4],
-
[172.7, 62.0], [155.0, 49.2], [156.5, 67.2], [164.0, 53.8], [160.9, 54.4],
-
[162.8, 58.0], [167.0, 59.8], [160.0, 54.8], [160.0, 43.2], [168.9, 60.5],
-
[158.2, 46.4], [156.0, 64.4], [160.0, 48.8], [167.1, 62.2], [158.0, 55.5],
-
[167.6, 57.8], [156.0, 54.6], [162.1, 59.2], [173.4, 52.7], [159.8, 53.2],
-
[170.5, 64.5], [159.2, 51.8], [157.5, 56.0], [161.3, 63.6], [162.6, 63.2],
-
[160.0, 59.5], [168.9, 56.8], [165.1, 64.1], [162.6, 50.0], [165.1, 72.3],
-
[166.4, 55.0], [160.0, 55.9], [152.4, 60.4], [170.2, 69.1], [162.6, 84.5],
-
[170.2, 55.9], [158.8, 55.5], [172.7, 69.5], [167.6, 76.4], [162.6, 61.4],
-
[167.6, 65.9], [156.2, 58.6], [175.2, 66.8], [172.1, 56.6], [162.6, 58.6],
-
[160.0, 55.9], [165.1, 59.1], [182.9, 81.8], [166.4, 70.7], [165.1, 56.8],
-
[177.8, 60.0], [165.1, 58.2], [175.3, 72.7], [154.9, 54.1], [158.8, 49.1],
-
[172.7, 75.9], [168.9, 55.0], [161.3, 57.3], [167.6, 55.0], [165.1, 65.5],
-
[175.3, 65.5], [157.5, 48.6], [163.8, 58.6], [167.6, 63.6], [165.1, 55.2],
-
[165.1, 62.7], [168.9, 56.6], [162.6, 53.9], [164.5, 63.2], [176.5, 73.6],
-
[168.9, 62.0], [175.3, 63.6], [159.4, 53.2], [160.0, 53.4], [170.2, 55.0],
-
[162.6, 70.5], [167.6, 54.5], [162.6, 54.5], [160.7, 55.9], [160.0, 59.0],
-
[157.5, 63.6], [162.6, 54.5], [152.4, 47.3], [170.2, 67.7], [165.1, 80.9],
-
[172.7, 70.5], [165.1, 60.9], [170.2, 63.6], [170.2, 54.5], [170.2, 59.1],
-
[161.3, 70.5], [167.6, 52.7], [167.6, 62.7], [165.1, 86.3], [162.6, 66.4],
-
[152.4, 67.3], [168.9, 63.0], [170.2, 73.6], [175.2, 62.3], [175.2, 57.7],
-
[160.0, 55.4], [165.1, 104.1], [174.0, 55.5], [170.2, 77.3], [160.0, 80.5],
-
[167.6, 64.5], [167.6, 72.3], [167.6, 61.4], [154.9, 58.2], [162.6, 81.8],
-
[175.3, 63.6], [171.4, 53.4], [157.5, 54.5], [165.1, 53.6], [160.0, 60.0],
-
[174.0, 73.6], [162.6, 61.4], [174.0, 55.5], [162.6, 63.6], [161.3, 60.9],
-
[156.2, 60.0], [149.9, 46.8], [169.5, 57.3], [160.0, 64.1], [175.3, 63.6],
-
[169.5, 67.3], [160.0, 75.5], [172.7, 68.2], [162.6, 61.4], [157.5, 76.8],
-
[176.5, 71.8], [164.4, 55.5], [160.7, 48.6], [174.0, 66.4], [163.8, 67.3]]
-
-
}, {
-
:name => 'Male',
-
:color => 'rgba(119, 152, 191, .5)',
-
:data => [[174.0, 65.6], [175.3, 71.8], [193.5, 80.7], [186.5, 72.6], [187.2, 78.8],
-
[181.5, 74.8], [184.0, 86.4], [184.5, 78.4], [175.0, 62.0], [184.0, 81.6],
-
[180.0, 76.6], [177.8, 83.6], [192.0, 90.0], [176.0, 74.6], [174.0, 71.0],
-
[184.0, 79.6], [192.7, 93.8], [171.5, 70.0], [173.0, 72.4], [176.0, 85.9],
-
[176.0, 78.8], [180.5, 77.8], [172.7, 66.2], [176.0, 86.4], [173.5, 81.8],
-
[178.0, 89.6], [180.3, 82.8], [180.3, 76.4], [164.5, 63.2], [173.0, 60.9],
-
[183.5, 74.8], [175.5, 70.0], [188.0, 72.4], [189.2, 84.1], [172.8, 69.1],
-
[170.0, 59.5], [182.0, 67.2], [170.0, 61.3], [177.8, 68.6], [184.2, 80.1],
-
[186.7, 87.8], [171.4, 84.7], [172.7, 73.4], [175.3, 72.1], [180.3, 82.6],
-
[182.9, 88.7], [188.0, 84.1], [177.2, 94.1], [172.1, 74.9], [167.0, 59.1],
-
[169.5, 75.6], [174.0, 86.2], [172.7, 75.3], [182.2, 87.1], [164.1, 55.2],
-
[163.0, 57.0], [171.5, 61.4], [184.2, 76.8], [174.0, 86.8], [174.0, 72.2],
-
[177.0, 71.6], [186.0, 84.8], [167.0, 68.2], [171.8, 66.1], [182.0, 72.0],
-
[167.0, 64.6], [177.8, 74.8], [164.5, 70.0], [192.0, 101.6], [175.5, 63.2],
-
[171.2, 79.1], [181.6, 78.9], [167.4, 67.7], [181.1, 66.0], [177.0, 68.2],
-
[174.5, 63.9], [177.5, 72.0], [170.5, 56.8], [182.4, 74.5], [197.1, 90.9],
-
[180.1, 93.0], [175.5, 80.9], [180.6, 72.7], [184.4, 68.0], [175.5, 70.9],
-
[180.6, 72.5], [177.0, 72.5], [177.1, 83.4], [181.6, 75.5], [176.5, 73.0],
-
[175.0, 70.2], [174.0, 73.4], [165.1, 70.5], [177.0, 68.9], [192.0, 102.3],
-
[176.5, 68.4], [169.4, 65.9], [182.1, 75.7], [179.8, 84.5], [175.3, 87.7],
-
[184.9, 86.4], [177.3, 73.2], [167.4, 53.9], [178.1, 72.0], [168.9, 55.5],
-
[157.2, 58.4], [180.3, 83.2], [170.2, 72.7], [177.8, 64.1], [172.7, 72.3],
-
[165.1, 65.0], [186.7, 86.4], [165.1, 65.0], [174.0, 88.6], [175.3, 84.1],
-
[185.4, 66.8], [177.8, 75.5], [180.3, 93.2], [180.3, 82.7], [177.8, 58.0],
-
[177.8, 79.5], [177.8, 78.6], [177.8, 71.8], [177.8, 116.4], [163.8, 72.2],
-
[188.0, 83.6], [198.1, 85.5], [175.3, 90.9], [166.4, 85.9], [190.5, 89.1],
-
[166.4, 75.0], [177.8, 77.7], [179.7, 86.4], [172.7, 90.9], [190.5, 73.6],
-
[185.4, 76.4], [168.9, 69.1], [167.6, 84.5], [175.3, 64.5], [170.2, 69.1],
-
[190.5, 108.6], [177.8, 86.4], [190.5, 80.9], [177.8, 87.7], [184.2, 94.5],
-
[176.5, 80.2], [177.8, 72.0], [180.3, 71.4], [171.4, 72.7], [172.7, 84.1],
-
[172.7, 76.8], [177.8, 63.6], [177.8, 80.9], [182.9, 80.9], [170.2, 85.5],
-
[167.6, 68.6], [175.3, 67.7], [165.1, 66.4], [185.4, 102.3], [181.6, 70.5],
-
[172.7, 95.9], [190.5, 84.1], [179.1, 87.3], [175.3, 71.8], [170.2, 65.9],
-
[193.0, 95.9], [171.4, 91.4], [177.8, 81.8], [177.8, 96.8], [167.6, 69.1],
-
[167.6, 82.7], [180.3, 75.5], [182.9, 79.5], [176.5, 73.6], [186.7, 91.8],
-
[188.0, 84.1], [188.0, 85.9], [177.8, 81.8], [174.0, 82.5], [177.8, 80.5],
-
[171.4, 70.0], [185.4, 81.8], [185.4, 84.1], [188.0, 90.5], [188.0, 91.4],
-
[182.9, 89.1], [176.5, 85.0], [175.3, 69.1], [175.3, 73.6], [188.0, 80.5],
-
[188.0, 82.7], [175.3, 86.4], [170.5, 67.7], [179.1, 92.7], [177.8, 93.6],
-
[175.3, 70.9], [182.9, 75.0], [170.8, 93.2], [188.0, 93.2], [180.3, 77.7],
-
[177.8, 61.4], [185.4, 94.1], [168.9, 75.0], [185.4, 83.6], [180.3, 85.5],
-
[174.0, 73.9], [167.6, 66.8], [182.9, 87.3], [160.0, 72.3], [180.3, 88.6],
-
[167.6, 75.5], [186.7, 101.4], [175.3, 91.1], [175.3, 67.3], [175.9, 77.7],
-
[175.3, 81.8], [179.1, 75.5], [181.6, 84.5], [177.8, 76.6], [182.9, 85.0],
-
[177.8, 102.5], [184.2, 77.3], [179.1, 71.8], [176.5, 87.9], [188.0, 94.3],
-
[174.0, 70.9], [167.6, 64.5], [170.2, 77.3], [167.6, 72.3], [188.0, 87.3],
-
[174.0, 80.0], [176.5, 82.3], [180.3, 73.6], [167.6, 74.1], [188.0, 85.9],
-
[180.3, 73.2], [167.6, 76.3], [183.0, 65.9], [183.0, 90.9], [179.1, 89.1],
-
[170.2, 62.3], [177.8, 82.7], [179.1, 79.1], [190.5, 98.2], [177.8, 84.1],
-
[180.3, 83.2], [180.3, 83.2]]
-
}]
-
}
-
}
-
end
-
1
def self.test_data()
-
{
-
:course_list => [["course 1",1],["course 2",2],["course 3",3]],
-
:assignment_list => [["assignment 1",1],["assignment 2",2],["assignment",3]],
-
:team_list => [["team 1",1],["team 2",2],["team 3",3]],
-
:chart_obj => Chart.data_template()[:bar]
-
}
-
end
-
end
-
1
module ChartsHelper
-
-
# labels: array of labels
-
# values: array of values
-
1
def self.get_pie_chart_url(labels, values)
-
if labels.length != values.length
-
return ""
-
end
-
-
address = "http://chart.apis.google.com/chart?cht=p3&chs=300x125"
-
max = 100.0
-
for value in values
-
max = value if value.to_f > max
-
end
-
-
max = max/100.0
-
-
value_string = "&chd=t:"
-
label_string = "&chl="
-
color_string = "&chco="
-
-
i = 0
-
for value in values
-
unless value == 0
-
-
value_string += (value.to_f/max).to_i.to_s + ","
-
label_string += labels[i].to_s + "|"
-
color_string += self.get_rg_color(i+0.5,values.length) + ","
-
end
-
i += 1
-
end
-
-
value_string = value_string[0..-2] # remove last comma
-
label_string = label_string[0..-2] # remove last "|"
-
color_string = color_string[0..-2] # remove last comma
-
-
address += value_string + label_string + color_string
-
end
-
-
# labels: array of labels
-
# values: array of values
-
# max: maximum possible value
-
1
def self.get_bar_chart_url(labels,values,max)
-
if labels.length != values.length
-
return ""
-
end
-
-
address = "http://chart.apis.google.com/chart?cht=bhs&chxt=x,y&chf=bg,s,dddddd&chtt=Average+response+score+by+question&chs=600x" + (labels.length*25+60).to_s
-
-
value_string = "&chd=t:"
-
label_string = "&chxl=0:|"
-
color_string = "&chco="
-
-
for j in 0..max
-
label_string += j.to_s + "|"
-
end
-
-
label_string += "1:|"
-
-
i = 0
-
for value in values
-
label_string += labels[labels.length - 1 - i].to_s + "|"
-
color_string += self.get_rg_color(value,max)+","
-
value_string += (value*100/max).to_i.to_s + ","
-
i += 1
-
end
-
-
value_string = value_string[0..-2] # remove last "|"
-
label_string = label_string[0..-2] # remove last "|"
-
color_string = color_string[0..-2] # remove last comma
-
-
address += value_string + label_string + color_string
-
end
-
-
-
1
def self.get_rg_color(value,max)
-
-
ratio = (value)/(max/2.0)
-
color = ""
-
-
if ratio < 1.0
-
level = sprintf("%02x", 256*ratio)
-
color = "ff" + level + level
-
elsif ratio == 1.0
-
color = "ffffff"
-
else
-
level = sprintf("%02x", 256*(2.0-ratio))
-
color = level + "ff" + level
-
end
-
-
return color
-
end
-
-
-
end
-
1
module CourseHelper
-
#determin the courses that a user associate with
-
1
def associated_courses(user)
-
#NOTE: testing for roles in general is a bad practice but since the data base does not provide clear
-
# way to get this association we have no other choice
-
case user.role_id
-
#admin and super admin should be able to see all courses
-
when Role.superadministrator.id
-
courses = Course.all
-
when Role.administrator.id
-
courses = Course.all
-
-
#instructors should be able to see their own courses
-
when Role.instructor.id
-
courses = Course.find_all_by_instructor_id(user.id)
-
-
#ta should be able to see all the course they are ta-ing
-
when Role.ta.id
-
ta_mappings = TaMapping.find_all_by_ta_id(user.id)
-
course_id_list = Array.new
-
ta_mappings.each do |ta_mapping|
-
course_id_list << ta_mapping.course_id
-
end
-
course_id_list.uniq!
-
courses = Array.new
-
course_id_list.each do |course_id|
-
courses << Course.find(course_id)
-
end
-
courses
-
-
#student should be able to see the course that they participate in
-
# to be safe we are not assuming that all assignment participants are in course participant
-
# and all assignment team participants are in assignment participants
-
when Role.student.id
-
#find all course that the student participate in
-
course_id_list = Array.new
-
course_participant_list = CourseParticipant.find_all_by_user_id(user.id)
-
course_participant_list.each do |course_participant|
-
course_id_list << course_participant.course.id
-
end
-
#find all assignment the student participated in
-
assignment_participant_list = AssignmentParticipant.find_all_by_user_id(user.id)
-
assignment_participant_list.each do |assignment_participant|
-
if !assignment_participant.assignment.course.nil?
-
course_id_list << assignment_participant.assignment.course.id
-
end
-
end
-
#find all teams the student participated in
-
teams_users = TeamsUser.find_all_by_user_id(user.id)
-
teams_users.each do |teams_user|
-
team = Team.find(teams_user.team_id)
-
if team.is_a?(AssignmentTeam)
-
if !team.assignment.course.nil?
-
course_id_list << team.assignment.course.id
-
end
-
elsif team.is_a?(CourseTeam)
-
course_id_list << team.course.id
-
end
-
end
-
course_id_list.uniq!
-
courses = Array.new
-
course_id_list.each do |course_id|
-
courses << Course.find(course_id)
-
end
-
courses
-
end
-
end
-
end
-
1
module CourseParticipantHelper
-
end
-
#This helper contains methods to manipulate due dates of topics in an assignment. This helper if used by
-
#sign_up_controller
-
1
module DeadlineHelper
-
-
#Creates a new topic deadline for topic specified by topic_id.
-
# The deadline itself is specified by due_date object which contains several values which specify
-
# type { submission deadline, metareview deadline, etc.} a set of other parameters that
-
#specify whether submission, review, metareview, etc. are allowed for the particular deadline
-
1
def create_topic_deadline(due_date, offset, topic_id)
-
topic_deadline = TopicDeadline.new
-
topic_deadline.topic_id = topic_id
-
topic_deadline.due_at = DateTime.parse(due_date.due_at.to_s) + offset.to_i
-
topic_deadline.deadline_type_id = due_date.deadline_type_id
-
topic_deadline.late_policy_id = due_date.late_policy_id
-
topic_deadline.submission_allowed_id = due_date.submission_allowed_id
-
topic_deadline.review_allowed_id = due_date.review_allowed_id
-
topic_deadline.review_of_review_allowed_id = due_date.review_of_review_allowed_id
-
topic_deadline.round = due_date.round
-
topic_deadline.save
-
end
-
-
# This function is used to set the starting due date for a group of topics belonging to an assignment.
-
# This function is used in building the dependency graph for preventing injection attacks as specified in the sign_up_controller.
-
1
def set_start_due_date(assignment_id,set_of_topics)
-
-
#Remember, in create_common_start_time_topics function we reversed the graph so reverse it back
-
set_of_topics = set_of_topics.reverse
-
-
set_of_topics_due_dates = Array.new
-
i=0
-
days_between_submissions = Assignment.find(assignment_id)['days_between_submissions'].to_i
-
set_of_topics.each { |set_of_topic|
-
set_of_due_dates = nil
-
if i==0
-
#take the first set from the table which user stores
-
set_of_due_dates = DueDate.find_all_by_assignment_id(assignment_id)
-
offset = 0
-
else
-
set_of_due_dates = TopicDeadline.find_all_by_topic_id(set_of_topics[i-1][0])
-
-
set_of_due_dates.sort! {|a,b| a.due_at <=> b.due_at}
-
-
offset = days_between_submissions
-
end
-
-
set_of_topic.each { |topic_id|
-
#if the due dates have already been created and the save dependency is being clicked,
-
#then delete existing n create again
-
prev_saved_due_dates = TopicDeadline.find_all_by_topic_id(topic_id)
-
-
#Only if there is a dependency for the topic
-
if !prev_saved_due_dates.nil?
-
num_due_dates = prev_saved_due_dates.length
-
#for each due date in the current topic he want to compare it to the previous due date
-
for x in 0..num_due_dates - 1
-
#we don't want the old date to move earlier in time so we save it as the new due date and destroy the old one
-
if DateTime.parse(set_of_due_dates[x].due_at.to_s) + offset.to_i < DateTime.parse(prev_saved_due_dates[x].due_at.to_s)
-
set_of_due_dates[x] = prev_saved_due_dates[x]
-
offset = 0
-
end
-
prev_saved_due_dates[x].destroy
-
end
-
end
-
-
set_of_due_dates.each {|due_date|
-
create_topic_deadline(due_date, offset, topic_id)
-
}
-
}
-
i = i+1
-
}
-
-
end
-
end
-
################################################################################
-
## ##
-
## THe following document has its codebase based on the following URL ##
-
## https://gist.github.com/5387d3ab48c538662c87 ##
-
## ##
-
## Redistribution and use in source and binary forms, with or without ##
-
## modification, are permitted provided that the following conditions ##
-
## are met: ##
-
## ##
-
## 1. Redistributions of source code must retain the above copyright ##
-
## notice, this list of conditions and the following disclaimer. ##
-
## ##
-
## 2. Redistributions in binary form must reproduce the above copyright ##
-
## notice, this list of conditions and the following disclaimer in the ##
-
## documentation and/or other materials provided with the distribution. ##
-
## ##
-
## 3. The name of the author may not be used to endorse or promote products ##
-
## derived from this software without specific prior written permission. ##
-
## ##
-
################################################################################
-
-
1
module DiffHelper
-
1
ADDED = 'A'
-
1
DELETED = 'D'
-
1
CHANGED = 'C'
-
1
UNCHANGED = 'U'
-
-
1
class InputFile < Array
-
-
1
attr_accessor :pointer
-
-
1
def initialize
-
self.pointer = 0
-
end
-
-
1
def current_line
-
self[self.pointer]
-
end
-
-
1
def advance_pointer!
-
self.pointer += 1
-
end
-
-
1
def find_current_line_in(other)
-
index = (other[other.pointer..-1] || []).index(self.current_line)
-
return index.nil? ? nil : other.pointer + index
-
end
-
end
-
-
1
class OutputFile < Array
-
-
1
class Line < String
-
1
attr_accessor :type, :original_number
-
-
1
def initialize(type, input_file)
-
self.type = type
-
return unless input_file
-
self.replace(input_file.current_line)
-
self.original_number = input_file.pointer + 1
-
input_file.advance_pointer!
-
end
-
-
end
-
-
1
def add_line(type, input_file = nil)
-
self.push(Line.new(type, input_file))
-
end
-
-
end
-
-
1
class Processor
-
-
1
attr_accessor :absolute_line_num
-
1
attr_accessor :first_file_array
-
1
attr_accessor :second_file_array
-
1
attr_accessor :comparison_array
-
-
1
attr_accessor :source, :target
-
1
attr_accessor :source_output, :target_output
-
-
1
def initialize(source_file_name, target_file_name)
-
@absolute_line_num = 0
-
@first_file_array = []
-
@second_file_array = []
-
@comparison_array = []
-
self.source = InputFile.new
-
self.target = InputFile.new
-
-
self.source_output = OutputFile.new
-
self.target_output = OutputFile.new
-
IO.readlines(source_file_name).each do |line|
-
self.source << line
-
end
-
IO.readlines(target_file_name).each do |line|
-
self.target << line
-
end
-
end
-
-
1
def handle_exactly_matched
-
@absolute_line_num += 1
-
@first_file_array << source.current_line
-
@second_file_array << target.current_line
-
@comparison_array << DiffHelper::UNCHANGED
-
source_output.add_line(:unchanged, source)
-
target_output.add_line(:unchanged, target)
-
end
-
-
1
def handle_line_changed
-
@absolute_line_num += 1
-
@first_file_array << source.current_line
-
@second_file_array << target.current_line
-
@comparison_array << DiffHelper::CHANGED
-
source_output.add_line(:changed, source)
-
target_output.add_line(:changed, target)
-
end
-
-
1
def handle_block_added(size)
-
size.times do
-
@absolute_line_num += 1
-
@first_file_array << ""#"$"
-
@second_file_array << target.current_line
-
@comparison_array << DiffHelper::ADDED
-
source_output.add_line(:added) # Empty line in the left side of the diff
-
target_output.add_line(:added, target)
-
end
-
end
-
-
1
def handle_block_deleted(size)
-
size.times do
-
@absolute_line_num+=1
-
@first_file_array << source.current_line
-
@second_file_array << ""#"$"
-
@comparison_array << DiffHelper::DELETED
-
source_output.add_line(:deleted, source)
-
target_output.add_line(:deleted) # Empty line in the right side of the diff
-
end
-
end
-
-
1
def process!
-
while ( source.pointer < source.size && target.pointer < target.size) do
-
matched = source.find_current_line_in(target)
-
if matched
-
if (matched > target.pointer)
-
deleted = target.find_current_line_in(source)
-
handle_block_deleted(deleted - source.pointer) if deleted
-
end
-
handle_block_added(matched - target.pointer)
-
handle_exactly_matched
-
else
-
found = target.find_current_line_in(source)
-
if found
-
handle_block_deleted(found - source.pointer)
-
else
-
handle_line_changed
-
end
-
end
-
end
-
-
handle_block_deleted(source.size - source.pointer)
-
handle_block_added(target.size - target.pointer)
-
-
return self
-
end
-
end
-
-
end
-
# TODO: Remove this helper, this code is not well-designed.
-
# Look at Assignment.contributor_to_review() as an example of a better approach
-
1
module DynamicReviewAssignmentHelper
-
-
# * The article was not written by the potential reviewer.
-
# * The article was not already reviewed by the potential reviewer.
-
# * The article is not on the same topic as the potential reviewer has previously written about.
-
# * The article does not already have the maximum number of potential reviews in progress.
-
# * The article has the minimum number of reviews for that assignment.
-
-
1
def self.review_assignment(assignment_id, reviewer_id, topic_id, review_type )
-
@assignment_id = assignment_id
-
@current_assignment = Assignment.find(assignment_id)
-
@reviewer_id = reviewer_id
-
@topic_id = topic_id
-
-
if (review_type == Assignment::RS_STUDENT_SELECTED)
-
return student_selected_review_assignment( )
-
else
-
return nil
-
end
-
end
-
-
1
def self.student_selected_review_assignment( )
-
-
# Get all the submissions available
-
@submissions_in_current_cycle = find_submissions_in_current_cycle()
-
# Based on round robin , build a Map ( paricipant_id , {0/1/-1} )
-
# The submissions in current cycle is already a sorted Map ( paricipant_id , review_count)
-
# Once a submission is picked , it has a higher review count and thus until all the
-
# existing submissions reach the same number , it is unavailable. If the review_count reaches the max #reviews required
-
# it is not available . ( 0 - available , 1 - currently not available & -1 not available)
-
-
return build_submissions_availability()
-
end
-
-
# Max no of reviews ? currently assuming 5
-
# The first element will have the least_review_count (as it is sorted)
-
# based on this build the Map
-
-
1
def self.build_submissions_availability()
-
least_review_count = -1;
-
max_no_reviews = 5
-
@submissions_availability = Hash.new
-
unless @submissions_in_current_cycle.nil?
-
@submissions_in_current_cycle.each { |submission|
-
-
if( least_review_count == -1)
-
least_review_count = submission[1]
-
end
-
if submission[0] != @reviewer_id
-
@submissions_availability[submission[0]] = get_state(least_review_count,submission[1],max_no_reviews)
-
end
-
}
-
end
-
return @submissions_availability
-
end
-
-
# The current submissions are sorted , it the #review_count == max_review_count
-
# it is not available and similarly #review_count > #least_review_count Currently
-
# not avaliable , else equal available.
-
-
1
def self.get_state(least_review_count,current_review_count,max_review_count)
-
if(current_review_count != -1 && current_review_count == max_review_count)
-
return -1
-
elsif(current_review_count != -1 && current_review_count > least_review_count)
-
return 1
-
elsif(current_review_count != -1 && current_review_count == least_review_count)
-
return 0
-
end
-
end
-
-
# Find all the submissions for this cycle
-
# Build a Map from (participant_id => review_count)
-
1
def self.find_submissions_in_current_cycle()
-
-
#
-
# If the user selected a topic, then filter by that topic first to get a list of all
-
# submissions that have been made for this particular assignment. The 'AssignmentParticipant'
-
# model represents a submission for an assignment (among other things).
-
#
-
-
# Make sure to filter out any submissions that do not have any related material. This avoids
-
# wasting time on submissions that have no content as well as avoiding duplicate reviews
-
# of team submissions.
-
if @topic_id.blank?
-
submissions_in_current_cycle = AssignmentParticipant.find_all_by_parent_id(@assignment_id)
-
else
-
submissions_in_current_cycle = AssignmentParticipant.find_all_by_topic_id_and_parent_id(@topic_id ,
-
@assignment_id)
-
end
-
submissions_in_current_cycle.reject! { |submission| !submission.has_submissions? }
-
-
# Create a new Hash to store the number of reviews that have already been done (or are in progress) for
-
# each submission.
-
@submission_review_count = Hash.new
-
submissions_in_current_cycle.each do |submission|
-
# Each 'ResponseMap' entry indicates a review has been performed or is in progress.
-
existing_maps = ResponseMap.find_all_by_reviewee_id_and_reviewed_object_id( submission.id, @assignment_id )
-
if existing_maps.nil?
-
@submission_review_count[submission.id] = 0 # There are no reviews in progress (potential or completed).
-
else
-
@submission_review_count[submission.id] = existing_maps.size
-
end
-
end
-
-
# Sort and return the list of submissions by the number of reviews that they have.
-
sorted_review_count = @submission_review_count.sort {|a, b| a[1]<=>b[1]}
-
return sorted_review_count
-
end
-
-
end
-
# Methods for dynamic review mapping
-
# called from Assignment class
-
-
1
module DynamicReviewMapping
-
1
def init()
-
teams = self.teams
-
@num_teams = teams.size # indicates the num of teams
-
students = self.participants
-
@num_students = students.size
-
populate_review_matrix(students, teams) # the matrix that maps reviewers and teams
-
@changed_cells = Array.new
-
@num_max = self.num_reviews* @num_students % @num_teams # the number of teams which can have the max. no. of reviewers
-
-
-
@min = self.num_reviews*@num_students/@num_teams # the min # of reviewers a team can have
-
if (@num_max == 0)
-
@max = @min
-
@num_max = @num_teams
-
else
-
@max = @min+1
-
end
-
-
# calculates the ones and zeros in each row and column
-
populate_row_matrices()
-
populate_column_matrices()
-
end
-
-
1
def assign_individual_reviewer(round_num)
-
stride = 1
-
authors = self.participants
-
reviewers = self.participants
-
if self.participants.size == 0
-
raise "No participants available for assignment"
-
end
-
-
for i in 0 .. reviewers.size - 1
-
current_reviewer_candidate = i
-
current_author_candidate = current_reviewer_candidate
-
for j in 0 .. (reviewers.size * num_reviews / authors.size) - 1 # This method potentially assigns authors different #s of reviews, if limit is non-integer
-
current_author_candidate = (current_author_candidate + stride) % authors.size
-
ParticipantReviewResponseMap.create(:reviewee_id => authors[current_author_candidate].id, :reviewer_id => reviewers[i].id, :reviewed_object_id => self.id)
-
end
-
end
-
end
-
-
1
def assign_reviewers_for_team(round_num)
-
init()
-
for i in 0..@num_students-1 do
-
if (row_enough_ones(i) == 1)
-
break
-
end
-
for j in 0..@num_teams-1 do
-
failed_mapping_col_wise = false;
-
successful_mapping_col_wise = false;
-
failed_mapping_row_wise = false;
-
successful_mapping_row_wise = false;
-
if (@team_review[i][j] == -1)
-
@team_review[i][j] = 1
-
@rows_ones[i] += 1
-
@columns_ones[j] += 1
-
if (col_enough_ones(j) == 1) #
-
if (toggle_col(j))
-
failed_mapping_col_wise = false
-
end
-
if (!failed_mapping_col_wise)
-
successful_mapping_col_wise = true
-
end
-
else
-
successful_mapping_col_wise = true
-
end
-
# setting flags for checking failed case
-
if(failed_mapping_col_wise)
-
successful_mapping_col_wise = false
-
end
-
if (successful_mapping_col_wise)
-
failed_mapping_col_wise = false
-
end
-
-
if ((row_enough_ones(i) == 1))
-
# backup the cells which may be needed to restore later if choice is invalid
-
for k in 0..@num_teams-1 do # for each remaining -1 in this row
-
if (@team_review[i][k]==-1)
-
change_cell(i, k, 0);
-
# if we do this assignment, will it force some students to do 1 too many reviews
-
if (col_enough_zeros(k) == 1)
-
if (!toggle_zeros_col(k))
-
failed_mapping_row_wise = true
-
end
-
end
-
end
-
end
-
else
-
successful_mapping_row_wise = true
-
end
-
# setting flags
-
if(failed_mapping_row_wise)
-
successful_mapping_row_wise = false
-
end
-
if (successful_mapping_row_wise)
-
failed_mapping_row_wise = false
-
end
-
-
if (failed_mapping_col_wise || failed_mapping_row_wise)
-
restore()
-
populate_row_matrices()
-
populate_column_matrices()
-
end
-
end
-
end
-
end
-
save_mapping(round_num)
-
end
-
-
1
def save_mapping (round_num)
-
i = 0
-
j = 0
-
self.participants.each{
-
| reviewer |
-
self.teams.each{
-
| reviewee |
-
if @team_review[i][j] == 1
-
TeamReviewResponseMap.create(:reviewer_id => reviewer.id, :reviewed_object_id => self.id, :reviewee_id => reviewee.id)
-
end
-
j += 1
-
}
-
j = 0
-
i += 1
-
}
-
end
-
-
1
def restore()
-
for i in 0..@changed_cells.length-1 do
-
@team_review[@changed_cells[i].row][@changed_cells[i].column] = @changed_cells[i].value;
-
end
-
@changed_cells.clear()
-
end
-
-
1
def populate_review_matrix(students, teams)
-
i = 0
-
j = 0
-
@team_review = Array.new(students.size).map!{ Array.new(teams.size)}
-
students.each{
-
| student |
-
if student.team != nil
-
teams.each{
-
| team |
-
if (student.team.id == team.id)
-
@team_review[i][j] = 0;
-
else
-
@team_review[i][j] = -1;
-
end
-
j += 1
-
}
-
j = 0
-
i += 1
-
end
-
}
-
end
-
-
1
def populate_row_matrices()
-
@rows_zeros = Array.new(@num_students, 0) # keeps the track of zeros in each row
-
@rows_ones = Array.new(@num_students, 0) # keeps the track of ones in each row
-
-
# populating row wise
-
for i in 0..@num_students-1 do
-
for j in 0..@num_teams-1 do
-
if (@team_review[i][j] == 0)
-
@rows_zeros[i] += 1
-
else
-
@rows_ones[i] += 1
-
end
-
end
-
end
-
end
-
-
1
def populate_column_matrices()
-
@columns_zeros = Array.new(@num_teams, 0)# keeps the track of zeros in each column
-
@columns_ones = Array.new(@num_teams, 0) # keeps the track of ones in each column
-
-
# populating column wise
-
for j in 0..@num_teams-1 do
-
for i in 0..@num_students-1 do
-
if (@team_review[i][j] == 0)
-
@columns_zeros[j] += 1
-
else
-
@columns_ones[j] += 1
-
end
-
end
-
end
-
end
-
-
-
1
class CellDescriptor
-
1
attr_accessor :row
-
1
attr_accessor :column
-
1
attr_accessor :value
-
1
def initialize (row, column, value)
-
@row, @column, @value = row, column, value
-
end
-
end
-
-
1
def change_cell(row, column, value)
-
old_value = @team_review[row][column]
-
@team_review[row][column] = value;
-
if (value == 0)
-
@rows_zeros[row]+=1;
-
@columns_zeros[column]+=1;
-
elsif(value == 1)
-
@rows_ones[row]+=1;
-
@columns_ones[column]+=1;
-
end
-
cell = CellDescriptor.new(row, column, old_value)
-
@changed_cells << cell
-
end
-
-
1
def row_enough_zeros(i)
-
# this function is used to toggle whether the student i has enough invalid reviewers
-
# returns 1 if # of '1's in row i is enough
-
# returns -1 if # of '1's in row i is more than enough
-
# returns 0 otherwise
-
toggle_val = (@num_teams-self.num_reviews)
-
if (@rows_zeros[i] == toggle_val)
-
return 1
-
elsif (@rows_zeros[i] > toggle_val)
-
return -1
-
else
-
return 0
-
end
-
end
-
-
1
def row_enough_ones(position)
-
# this function is used to toggle whether the student i has enough valid reviewers
-
# returns 1 if # of '1's in row i is enough
-
# returns -1 if # of '1's in row i is more than enough
-
# returns 0 otherwise
-
if (@rows_ones[position] == self.num_reviews)
-
return 1
-
elsif (@rows_ones[position] > self.num_reviews)
-
return -1
-
else
-
return 0
-
end
-
end
-
-
1
def col_enough_zeros(position)
-
# this function is used to toggle whether team j has enough invalid reviewers
-
# returns 1 if # of '1's in column j is enough
-
# returns -1 if # of '1's in column j is more than enough
-
# returns 0 otherwise
-
count = 0
-
for k in 0..@columns_ones.length-1 do
-
if ((position != k) && @columns_ones[k] == (@num_students-@min))
-
count +=1
-
end
-
end
-
-
max_allowed_to_have_min_reviewers = @num_teams-@num_max
-
max_allowed_to_have_min_reviewers = @num_max if (max_allowed_to_have_min_reviewers == 0)
-
if (count == max_allowed_to_have_min_reviewers)
-
if (@columns_zeros[position] == (@num_students-@max))
-
return 1
-
elsif (@columns_zeros[position] > (@num_students-@max))
-
return -1
-
else
-
return 0
-
end
-
elsif (count < max_allowed_to_have_min_reviewers)
-
if (@columns_zeros[position] == (@num_students-@min))
-
return 1
-
elsif (@columns_zeros[position] > (@num_students-@min))
-
return -1
-
else
-
return 0
-
end
-
end
-
return -1
-
end
-
-
-
1
def col_enough_ones(position)
-
# this function is used to toggle whether team j has enough valid reviewers
-
# returns 1 if # of '1's in column j is enough
-
# returns -1 if # of '1's in column j is more than enough
-
# returns 0 otherwise
-
count = 0
-
for k in 0..@columns_ones.length-1 do
-
if (@columns_ones[k] == @max)
-
count +=1
-
end
-
end
-
-
if (count == @num_max)
-
if (@columns_ones[position] == @min)
-
return 1
-
elsif (@columns_ones[position] > @min)
-
return -1
-
else
-
return 0
-
end
-
elsif (count < @num_max)
-
if (@columns_ones[position] == @max)
-
return 1
-
elsif (@columns_ones[position] > @max)
-
return -1
-
else
-
return 0
-
end
-
end
-
return -1
-
end
-
-
1
def toggle_zeros_row(position)
-
# Precondition: This reviewers has n-r invalid mapping assignments.
-
# Set remaining -1s to 1s
-
for j in 0..@num_teams-1 do
-
if (@team_review[position][j]==-1)
-
change_cell(position, j, 1)
-
if (col_enough_ones(j) == -1)
-
return false
-
elsif (col_enough_ones(j) == 1)
-
val = toggle_col(j)
-
if (!val)
-
return false
-
end
-
end
-
end
-
end
-
return true
-
end
-
-
1
def toggle_zeros_col(position)
-
# Precondition: This reviewers has n-r invalid mapping assignments.
-
# Set remaining -1s to 1s
-
for i in 0..@num_students-1 do
-
if (@team_review[i][position]==-1)
-
change_cell(i, position, 1);
-
if (row_enough_ones(position) == -1)
-
return false
-
elsif (row_enough_ones(position) == 1)
-
val = toggle_row(position)
-
if (!val)
-
return false
-
end
-
end
-
end
-
end
-
return true
-
end
-
-
-
1
def toggle_row(position)
-
# Precondition: This reviewers has enough teams to review. So set remaining "-1"s to "0"s
-
# Set remaining -1s to 0s
-
for j in 0..@num_teams-1 do
-
if (@team_review[position][j]==-1)
-
change_cell(position, j, 0)
-
if (col_enough_zeros(j) == -1)
-
return false
-
elsif (col_enough_zeros(j) == 1)
-
val = toggle_zeros_col(j)
-
if (!val)
-
return false
-
end
-
end
-
end
-
end
-
return true
-
end
-
-
-
1
def toggle_col(position)
-
# Precondition: This reviewers has enough teams to review. So set remaining "-1"s to "0"s
-
# Set remaining -1s to 0s
-
for i in 0..@num_students-1 do
-
if (@team_review[i][position]==-1)
-
change_cell(i, position, 0)
-
if (row_enough_zeros(position) == -1)
-
return false
-
elsif (row_enough_zeros(position) == 1)
-
val = toggle_zeros_row(position)
-
if (!val)
-
return false
-
end
-
end
-
end
-
end
-
return true
-
end
-
-
-
#--------------METHODS BELOW FOR STAGGERED DEADLINE ASSIGNMENT / Assignment with signup sheet-----------------
-
-
#TODO: refactor later to merge with generic code. All the 3 functions have lot of code that is common
-
#and all 3 functions work on more or less the same algo
-
-
1
def assign_reviewers_automatically(num_reviews, num_review_of_reviews)
-
#ACS Removed the if condition(and corressponding else) which differentiate assignments as team and individual assignments
-
# to treat all assignments as team assignments
-
review_message = assign_reviewers_team(num_reviews)
-
metareview_message = assign_metareviewers(num_review_of_reviews, @assignment)
-
-
return review_message.to_s + metareview_message.to_s
-
end
-
-
1
def assign_reviewers_team(num_reviews)
-
-
@assignment = self
-
-
@show_message = false
-
-
number_of_reviews = num_reviews.to_i
-
-
contributors = SignUpTopic.find_by_sql("SELECT creator_id
-
FROM sign_up_topics as t,signed_up_users as u
-
WHERE t.assignment_id =" + @assignment.id.to_s + " and u.topic_id = t.id")
-
-
users = Array.new
-
mappings = Hash.new
-
reviews_per_team = 0
-
#convert to just an array of contributors(team_ids). Topics which needs review.
-
if !contributors.nil?
-
contributors.collect! {|contributor| contributor['creator_id'].to_i}
-
else
-
#TODO: Give up, no work to review ..
-
end
-
-
contributors.each { |contributor|
-
team_users = TeamsUser.find_all_by_team_id(contributor)
-
team_users.each { |team_user|
-
users.push(team_user['user_id'])
-
}
-
}
-
-
if users.size != 0
-
reviews_per_team = ((users.size.to_f * number_of_reviews.to_f)/contributors.size.to_f).ceil
-
else
-
#TODO: Give up, no work to reviewers ..
-
end
-
-
contributors.each { |contributor|
-
#initialize mappings
-
mappings[contributor] = Array.new(reviews_per_team)
-
}
-
-
-
#-------------initialize user_review_count----------------
-
user_review_count = Hash.new
-
users.each {|user|
-
user_review_count[user] = number_of_reviews
-
}
-
-
#-------------initialize team_reviewers_count-------------
-
team_reviewers_count = Hash.new
-
contributors.each {|contributor|
-
team_reviewers_count[contributor] = reviews_per_team
-
}
-
-
temp_users = users.clone
-
-
for i in 1..users.size
-
#randomly select a user from the list
-
user = temp_users[(rand(temp_users.size)).round]
-
-
#create a list of team_ids this user can review
-
users_team_id = Team.find_by_sql("SELECT t.id
-
FROM teams t, teams_users u
-
WHERE t.parent_id = #{@assignment.id.to_s} and t.id = u.team_id and u.user_id = #{user.to_s}")
-
-
temp_contributors = contributors.clone
-
temp_contributors.delete(users_team_id[0].id)
-
-
topic_team_id = Hash.new
-
temp_contributors.each {|contributor|
-
participant = Participant.find(:all,
-
:joins => "INNER JOIN teams_users ON participants.user_id = teams_users.user_id",
-
:conditions => "teams_users.team_id = #{contributor} AND participants.parent_id = #{@assignment.id}")
-
topic_team_id[contributor] = participant[0].topic_id
-
}
-
-
-
#Get topic count.
-
topic_count = Hash.new
-
topic_team_id.each {|record|
-
if (topic_count.has_key?(record[1]))
-
topic_count[record[1]] = topic_count[record[1]] + 1
-
else
-
topic_count[record[1]] = 1
-
end
-
}
-
-
i=0
-
#sort topic on count(this will be in ascending)
-
temp_topic_count = topic_count.sort {|a, b| a[1]<=>b[1]}
-
-
while user_review_count[user] != 0
-
#pick the last one (max count); topic[0] -> topic_id and topic[1] -> count
-
topic = temp_topic_count.last
-
-
#if there are no topics this user can review move on to next user
-
if topic.nil?
-
break
-
end
-
-
teams_to_assigned = Array.new
-
#check whether it's the user's topic
-
users_topic_id = Participant.find_by_parent_id_and_user_id(@assignment.id, user)['topic_id']
-
-
if (topic[0].to_i == users_topic_id.to_i && number_of_reviews < topic[1]) || topic[0].to_i != users_topic_id.to_i
-
#go thru team reviewers and find the team which worked on this topic
-
topic_team_id.each {|topic_team|
-
if topic_team[1].to_i == topic[0].to_i
-
#Also before pushing check whether this user is assigned to review this topic earlier
-
if mappings[topic_team[0]].index(user).nil?
-
teams_to_assigned.push(topic_team[0])
-
end
-
end
-
}
-
#here update the mappings datastructure which will be later used to update mappings table
-
teams_to_assigned.each {|team|
-
if team_reviewers_count[team] != 0 && user_review_count[user] != 0
-
mappings[team][(team_reviewers_count[team].to_i) -1] = user
-
team_reviewers_count[team] = (team_reviewers_count[team].to_i) - 1
-
user_review_count[user] = user_review_count[user] - 1
-
else
-
if user_review_count[user] == 0
-
#We are done with this user
-
break
-
end
-
end
-
}
-
else
-
#don't assign anything.
-
end
-
-
#remove that topic from the list
-
temp_topic_count.each {|temp_topic|
-
if temp_topic[0] == topic[0]
-
temp_topic_count.delete(temp_topic)
-
end
-
}
-
-
#just in case if this loop runs infinitely; can be removed once code stabilizes
-
#if (i>user_review_count[user]+10)
-
# break
-
#else
-
# i= i + 1
-
#end
-
end
-
temp_users.delete(user)
-
end
-
-
mappings.each {|mapping|
-
#mapping[0]=team_id and mapping[1]=users(array) assigned for reviewing this team
-
for i in 0..mapping[1].size-1
-
if mapping[1][i].nil?
-
#*try* double the number of users to assign a reviewer to this topic
-
for j in (1..users.size*2)
-
random_index = rand(users.size-1)
-
-
#check whether this guy is not part of the team
-
team = TeamsUser.find_by_team_id_and_user_id(mapping[0], users[random_index])
-
#if team is nil then this user is not part of the team
-
#Also check whether this user has not yet been assigned to review this team
-
if team.nil? && mapping[1].index(users[random_index]).nil?
-
mapping[1][i] = users[random_index]
-
team_reviewers_count[mapping[0]] = (team_reviewers_count[mapping[0]].to_i) - 1
-
user_review_count[users[random_index]] = user_review_count[users[random_index]] - 1
-
break
-
end
-
end
-
end
-
end
-
}
-
-
message = "<b>Some students have been assigned more/less than #{number_of_reviews} review(s). </b><br\>"
-
-
#reviewer_assignment_success = true
-
-
user_review_count.each{|user|
-
if user[1] > 0
-
#reviewer_assignment_success = false
-
message_participant = Participant.find_by_parent_id_and_user_id(@assignment.id, user[0])
-
users_fullname = message_participant.fullname
-
users_name = message_participant.name
-
message = message + "<li>" + users_fullname + "("+ users_name.to_s + "): -" + user[1].to_i.abs.to_s + "</li>"
-
@show_message = true
-
elsif user[1] < 0
-
@show_message = true
-
message_participant = Participant.find_by_parent_id_and_user_id(@assignment.id, user[0])
-
users_fullname = message_participant.fullname
-
users_name = message_participant.name
-
message = message + "<li>" +users_fullname + "("+ users_name.to_s + "): +" + user[1].to_i.abs.to_s + "</li>"
-
else
-
#do nothing
-
end
-
}
-
-
-
begin
-
#Actual mapping
-
mappings.each {|mapping|
-
team_id = mapping[0]
-
reviewers = mapping[1]
-
-
reviewers.each{|reviewer|
-
participant = Participant.find_by_parent_id_and_user_id(@assignment.id, reviewer)
-
#reviewer, and hence participant could be nil when algo couldn't find someone to review somebody's work
-
if !participant.nil?
-
reviewer_id = participant.id
-
if TeamReviewResponseMap.find(:first, :conditions => ['reviewee_id = ? and reviewer_id = ?', team_id, reviewer_id]).nil?
-
TeamReviewResponseMap.create(:reviewee_id => team_id, :reviewer_id => reviewer_id, :reviewed_object_id => @assignment.id)
-
else
-
#if there is such a review mapping just skip it. Or it can be handled by informing
-
#the instructor(TODO:)
-
end
-
end
-
}
-
}
-
if @show_message == true
-
return message
-
end
-
rescue Exception => exc
-
#revert the mapping
-
response_mappings = TeamReviewResponseMap.find_all_by_reviewed_object_id(@assignment.id)
-
if !response_mappings.nil?
-
response_mappings.each {|response_mapping|
-
response_mapping.delete
-
}
-
end
-
return "Automatic assignment failed!"
-
end
-
-
-
end
-
-
1
def assign_reviewers_individual(num_reviews)
-
@assignment = self
-
@show_message = false
-
number_of_reviews = num_reviews.to_i
-
-
contributors = SignUpTopic.find_by_sql("SELECT creator_id
-
FROM sign_up_topics as t,signed_up_users as u
-
WHERE t.assignment_id =" + @assignment.id.to_s + " and u.topic_id = t.id")
-
-
users = Array.new
-
mappings = Hash.new
-
reviews_per_user = 0
-
#convert to just an array of contributors(user_ids). Topics which needs review.
-
if !contributors.nil?
-
contributors.collect! {|contributor| contributor['creator_id'].to_i}
-
else
-
#TODO: Give up, no work to review ..
-
end
-
-
#contributors.each { |contributor|
-
# team_users = TeamsUser.find_all_by_team_id(contributor)
-
# team_users.each { |team_user|
-
# users.push(team_user['user_id'])
-
# }
-
#}
-
-
users = contributors.clone
-
-
if users.size != 0
-
reviews_per_user = ((users.size.to_f * number_of_reviews.to_f)/contributors.size.to_f).ceil
-
else
-
#TODO: Give up, no work to reviewers ..
-
end
-
-
contributors.each { |contributor|
-
#initialize mappings
-
mappings[contributor] = Array.new(reviews_per_user)
-
}
-
-
-
#-------------initialize user_review_count----------------
-
user_review_count = Hash.new
-
users.each {|user|
-
user_review_count[user] = number_of_reviews
-
}
-
-
#-------------initialize team_reviewers_count-------------
-
user_reviewers_count = Hash.new
-
contributors.each {|contributor|
-
user_reviewers_count[contributor] = reviews_per_user
-
}
-
-
temp_users = users.clone
-
-
for n in 1..users.size
-
#randomly select a user from the list
-
user = temp_users[(rand(temp_users.size)).round]
-
#create a list of user_ids this user can review
-
#users_team_id = Team.find_by_sql("SELECT t.id
-
# FROM teams t, teams_users u
-
# WHERE t.parent_id = #{@assignment.id.to_s} and t.id = u.team_id and u.user_id = #{user.to_s}")
-
-
temp_contributors = contributors.clone
-
temp_contributors.delete(user)
-
-
topic_user_id = Hash.new
-
temp_contributors.each {|contributor|
-
participant = Participant.find_all_by_user_id_and_parent_id(contributor, @assignment.id)
-
topic_user_id[contributor] = participant[0].topic_id
-
}
-
-
-
#Get topic count.
-
topic_count = Hash.new
-
topic_user_id.each {|record|
-
if (topic_count.has_key?(record[1]))
-
topic_count[record[1]] = topic_count[record[1]] + 1
-
else
-
topic_count[record[1]] = 1
-
end
-
}
-
-
i=0
-
#sort topic on count(this will be in ascending)
-
temp_topic_count = topic_count.sort {|a, b| a[1]<=>b[1]}
-
-
while user_review_count[user] != 0
-
#pick the last one (max count); topic[0] -> topic_id and topic[1] -> count
-
topic = temp_topic_count.last
-
-
#if there are no topics this user can review move on to next user
-
if topic.nil?
-
break
-
end
-
-
users_to_be_assigned = Array.new
-
#check whether it's the user's topic
-
users_topic_id = Participant.find_by_parent_id_and_user_id(@assignment.id, user)['topic_id']
-
-
if (topic[0].to_i == users_topic_id.to_i && number_of_reviews < topic[1]) || topic[0].to_i != users_topic_id.to_i
-
-
-
#go thru reviewers and find the reviewers who worked on this topic
-
topic_user_id.each {|topic_user|
-
if topic_user[1].to_i == topic[0].to_i
-
#Also before pushing check whether this user is assigned to review this topic earlier
-
if mappings[topic_user[0]].index(user).nil?
-
users_to_be_assigned.push(topic_user[0])
-
end
-
end
-
}
-
#here update the mappings datastructure which will be later used to update mappings table
-
users_to_be_assigned.each {|reviewer|
-
if user_reviewers_count[reviewer] != 0 && user_review_count[user] != 0
-
mappings[reviewer][(user_reviewers_count[reviewer].to_i) -1] = user
-
user_reviewers_count[reviewer] = (user_reviewers_count[reviewer].to_i) - 1
-
user_review_count[user] = user_review_count[user] - 1
-
else
-
if user_review_count[user] == 0
-
#We are done with this user
-
break
-
end
-
end
-
}
-
else
-
#don't assign anything.
-
end
-
-
#remove that topic from the list
-
temp_topic_count.each {|temp_topic|
-
if temp_topic[0] == topic[0]
-
temp_topic_count.delete(temp_topic)
-
end
-
}
-
-
#just in case if this loop runs infinitely; can be removed once code stabilizes
-
#if (i>user_review_count[user]+10)
-
# break
-
#else
-
# i= i + 1
-
#end
-
end
-
temp_users.delete(user)
-
end
-
-
-
-
mappings.each {|mapping|
-
#mapping[0]=team_id and mapping[1]=users(array) assigned for reviewing this team
-
for i in 0..mapping[1].size-1
-
if mapping[1][i].nil?
-
#*try* double the number of users times to assign a reviewer to this topic
-
for j in (1..users.size*2)
-
random_index = rand(users.size-1)
-
-
#check whether this randomly picked user is not the contributor
-
#Also check whether this user has not yet been assigned to review this team
-
if mapping[0].to_i != users[random_index].to_i && mapping[1].index(users[random_index]).nil?
-
mapping[1][i] = users[random_index]
-
user_reviewers_count[mapping[0]] = (user_reviewers_count[mapping[0]].to_i) - 1
-
user_review_count[users[random_index]] = user_review_count[users[random_index]] - 1
-
break
-
end
-
end
-
end
-
end
-
}
-
-
message = "<b>Some students have been assigned more/less than #{number_of_reviews} review(s). </b><br\>"
-
-
#reviewer_assignment_success = true
-
-
user_review_count.each{|user|
-
if user[1] > 0
-
#reviewer_assignment_success = false
-
message_participant = Participant.find_by_parent_id_and_user_id(@assignment.id, user[0])
-
users_fullname = message_participant.fullname
-
users_name = message_participant.name
-
message = message + "<li>" + users_fullname + "("+ users_name.to_s + "): -" + user[1].to_i.abs.to_s + "</li>"
-
@show_message = true
-
elsif user[1] < 0
-
@show_message = true
-
message_participant = Participant.find_by_parent_id_and_user_id(@assignment.id, user[0])
-
users_fullname = message_participant.fullname
-
users_name = message_participant.name
-
message = message + "<li>" +users_fullname + "("+ users_name.to_s + "): +" + user[1].to_i.abs.to_s + "</li>"
-
else
-
#do nothing
-
end
-
}
-
-
-
begin
-
#Actual mapping
-
mappings.each {|mapping|
-
reviewee = mapping[0]
-
reviewers = mapping[1]
-
-
reviewee_participant = Participant.find_by_parent_id_and_user_id(@assignment.id, reviewee)
-
-
if !reviewee_participant.nil?
-
reviewers.each{|reviewer|
-
participant = Participant.find_by_parent_id_and_user_id(@assignment.id, reviewer)
-
#reviewer, and hence participant could be nil when algo couldn't find someone to review somebody's work
-
if !participant.nil?
-
reviewer_id = participant.id
-
if ParticipantReviewResponseMap.find(:first, :conditions => ['reviewee_id = ? and reviewer_id = ?', reviewee_participant.id, reviewer_id]).nil?
-
ParticipantReviewResponseMap.create(:reviewee_id => reviewee_participant.id, :reviewer_id => reviewer_id, :reviewed_object_id => @assignment.id)
-
else
-
#if there is such a review mapping just skip it. Or it can be handled by informing
-
#the instructor(TODO:)
-
end
-
end
-
}
-
end
-
}
-
-
if @show_message == true
-
return message
-
end
-
rescue Exception => exc
-
#revert the mapping
-
response_mappings = ResponseMap.find_by_reviewed_object_id_and_type(@assignment.id, "ParticipantReviewResponseMap")
-
if !response_mappings.nil?
-
response_mappings.each {|response_mapping|
-
response_mapping.delete
-
}
-
end
-
return "Automatic assignment failed! Please try again with different number of reviews."
-
# include "#{exc.message}" to the above message to find what the error was.."
-
end
-
-
-
end
-
-
1
def assign_metareviewers(num_review_of_reviews, assignment)
-
-
@show_message = false
-
-
@assignment = assignment
-
number_of_reviews = num_review_of_reviews.to_i
-
-
if @assignment.team_assignment?
-
contributors = TeamReviewResponseMap.find_all_by_reviewed_object_id(@assignment.id)
-
else
-
contributors = ParticipantReviewResponseMap.find_all_by_reviewed_object_id(@assignment.id)
-
end
-
-
users = Array.new
-
mappings = Hash.new
-
reviews_per_user = 0
-
-
#convert to just an array of contributors(user_ids). Topics which needs review.
-
if !contributors.nil?
-
contributors.collect! {|contributor| contributor['id'].to_i}
-
else
-
#TODO: Give up, no work to review ..
-
end
-
-
#contributors.each { |contributor|
-
# team_users = TeamsUser.find_all_by_team_id(contributor)
-
# team_users.each { |team_user|
-
# users.push(team_user['user_id'])
-
# }
-
#}
-
-
contributors.each {|contributor|
-
map = ResponseMap.find(contributor)
-
participant = Participant.find(map.reviewer_id)
-
users.push(participant.user_id)
-
}
-
-
users = users.uniq
-
-
if (users.size * number_of_reviews) < contributors.size
-
#TODO: handle with error message
-
return "<br/><b>Insufficient metareviewers!</b>"
-
end
-
-
if users.size != 0
-
reviews_per_user = ((users.size.to_f * number_of_reviews.to_f)/contributors.size.to_f).ceil
-
else
-
#TODO: Give up, no reviewers ..
-
end
-
contributors.each { |contributor|
-
#initialize mappings
-
mappings[contributor] = Array.new(reviews_per_user)
-
}
-
-
-
#-------------initialize user_review_count----------------
-
user_review_count = Hash.new
-
users.each {|user|
-
user_review_count[user] = number_of_reviews
-
}
-
-
#-------------initialize team_reviewers_count-------------
-
user_reviewers_count = Hash.new
-
contributors.each {|contributor|
-
user_reviewers_count[contributor] = reviews_per_user
-
}
-
-
temp_users = users.clone
-
-
for i in 1..users.size
-
#randomly select a user from the list
-
user = temp_users[(rand(temp_users.size)).round]
-
temp_contributors = contributors.clone
-
participant = Participant.find_by_parent_id_and_user_id(@assignment.id, user)
-
if !participant.nil?
-
contributors.each {|contributor|
-
map = ResponseMap.find(contributor)
-
#ACS Removed the if condition(and corressponding else) which differentiate assignments as team and individual assignments
-
# to treat all assignments as team assignments
-
team_members = TeamsUser.find_all_by_team_id(map.reviewee_id)
-
if !team_members.nil?
-
team_members.each{|team_member|
-
if team_member.user_id == user
-
temp_contributors.delete(contributor)
-
end
-
}
-
end
-
#also check whether this user was not a reviewer
-
if map.reviewer_id == participant.id
-
temp_contributors.delete(contributor)
-
end
-
}
-
end
-
topic_user_id = Hash.new
-
temp_contributors.each {|contributor|
-
map = ResponseMap.find(contributor)
-
#participant = Participant.find_all_by_user_id_and_parent_id(map.reviewee_id, @assignment.id)
-
#ACS Removed the if condition(and corressponding else) which differentiate assignments as team and individual assignments
-
# to treat all assignments as team assignments
-
#We would have just one member for an individual assignment.
-
team_members = TeamsUser.find_all_by_team_id(map.reviewee_id)
-
if !team_members.nil?
-
participant = Participant.find_by_parent_id_and_user_id(@assignment.id, team_members[0].user_id)
-
topic_user_id[contributor] = participant.topic_id
-
end
-
}
-
-
#Get topic count.
-
topic_count = Hash.new
-
topic_user_id.each {|record|
-
if (topic_count.has_key?(record[1]))
-
topic_count[record[1]] = topic_count[record[1]] + 1
-
else
-
topic_count[record[1]] = 1
-
end
-
}
-
-
i=0
-
#sort topic on count(this will be in ascending)
-
temp_topic_count = topic_count.sort {|a, b| a[1]<=>b[1]}
-
-
while user_review_count[user] != 0
-
#pick the last one (max count); topic[0] -> topic_id and topic[1] -> count
-
topic = temp_topic_count.last
-
#if there are no topics this user can review move on to next user
-
if topic.nil?
-
break
-
end
-
-
users_to_be_assigned = Array.new
-
#check whether it's the user's topic
-
users_topic_id = Participant.find_by_parent_id_and_user_id(@assignment.id, user)['topic_id']
-
-
#go thru reviewers and find the reviewers who worked on this topic
-
-
topic_user_id.each {|topic_user|
-
-
if topic_user[1].to_i == topic[0].to_i
-
#Also before pushing check whether this user is assigned to review this reviewer earlier
-
if mappings[topic_user[0]].index(user).nil?
-
users_to_be_assigned.push(topic_user[0])
-
-
end
-
end
-
}
-
#here update the mappings datastructure which will be later used to update mappings table
-
users_to_be_assigned.each {|reviewer|
-
if user_reviewers_count[reviewer] != 0 && user_review_count[user] != 0
-
mappings[reviewer][(user_reviewers_count[reviewer].to_i) -1] = user
-
-
user_reviewers_count[reviewer] = (user_reviewers_count[reviewer].to_i) - 1
-
user_review_count[user] = user_review_count[user] - 1
-
else
-
if user_review_count[user] == 0
-
#We are done with this user
-
break
-
end
-
end
-
}
-
#else
-
#don't assign anything.
-
#end
-
-
#remove that topic from the list
-
temp_topic_count.each {|temp_topic|
-
if temp_topic[0] == topic[0]
-
temp_topic_count.delete(temp_topic)
-
end
-
}
-
-
#just in case if this loop runs infinitely; can be removed once code stabilizes
-
#if (i>user_review_count[user]+10)
-
# break
-
#else
-
# i= i + 1
-
#end
-
end
-
temp_users.delete(user)
-
-
end
-
-
mappings.each {|mapping|
-
#mapping[0]=team_id and mapping[1]=users(array) assigned for reviewing this team
-
for i in 0..mapping[1].size-1
-
-
if mapping[1][i].nil?
-
#*try* double the number of users times to assign a reviewer to this topic
-
for j in (1..users.size*4)
-
user_can_review = true
-
random_index = rand(users.size-1)
-
-
#check whether this randomly picked user is not the contributor
-
#Also check whether this user has not yet been assigned to review this team/user
-
participant = Participant.find_by_parent_id_and_user_id(@assignment.id, users[random_index])
-
-
map = ResponseMap.find(mapping[0])
-
-
#ACS Removed the if condition(and corressponding else) which differentiate assignments as team and individual assignments
-
# to treat all assignments as team assignments
-
team_members = TeamsUser.find_all_by_team_id(map.reviewee_id)
-
-
team_members.each {|team_member|
-
if team_member.user_id == users[random_index]
-
user_can_review = false
-
end
-
}
-
if participant.id == map.reviewer_id
-
user_can_review = false
-
end
-
-
if user_can_review == true && mapping[1].index(users[random_index]).nil?
-
-
mapping[1][i] = users[random_index]
-
user_reviewers_count[mapping[0]] = (user_reviewers_count[mapping[0]].to_i) - 1
-
user_review_count[users[random_index]] = user_review_count[users[random_index]] - 1
-
break
-
-
end
-
end
-
end
-
end
-
}
-
-
message = "<br/> <b>Some students have been assigned more/less than #{number_of_reviews} metareview(s). </b><br/>"
-
-
#reviewer_assignment_success = true
-
-
user_review_count.each{|user|
-
if user[1] > 0
-
#reviewer_assignment_success = false
-
message_participant = Participant.find_by_parent_id_and_user_id(@assignment.id, user[0])
-
users_fullname = message_participant.fullname
-
users_name = message_participant.name
-
message = message + "<li>" + users_fullname + "("+ users_name.to_s + "): -" + user[1].to_i.abs.to_s + "</li>"
-
@show_message = true
-
elsif user[1] < 0
-
@show_message = true
-
message_participant = Participant.find_by_parent_id_and_user_id(@assignment.id, user[0])
-
users_fullname = message_participant.fullname
-
users_name = message_participant.name
-
message = message + "<li>" +users_fullname + "("+ users_name.to_s + "): +" + user[1].to_i.abs.to_s + "</li>"
-
else
-
#do nothing
-
end
-
}
-
-
-
begin
-
#Actual mapping
-
mappings.each {|mapping|
-
#reviewee = mapping[0]
-
reviewers = mapping[1]
-
-
map = ResponseMap.find(mapping[0])
-
-
-
reviewers.each{|reviewer|
-
participant = Participant.find_by_parent_id_and_user_id(@assignment.id, reviewer)
-
#reviewer, and hence participant could be nil when algo couldn't find someone to review somebody's work
-
if !participant.nil?
-
reviewer_id = participant.id
-
if MetareviewResponseMap.find(:first, :conditions => ['reviewee_id = ? and reviewer_id = ? and reviewed_object_id = ?', map.reviewer_id, reviewer_id,mapping[0]]).nil?
-
MetareviewResponseMap.create(:reviewee_id => map.reviewer_id, :reviewer_id => reviewer_id, :reviewed_object_id => mapping[0])
-
else
-
#if there is such a review mapping just skip it. Or it can be handled by informing
-
#the instructor(TODO:..)
-
end
-
end
-
}
-
-
}
-
temp_message = ""
-
-
if @show_message == true
-
return message + temp_message
-
end
-
rescue Exception => exc
-
#revert the mapping
-
response_mappings = MetareviewResponseMap.find_all_by_reviewed_object_id(@assignment.id)
-
if !response_mappings.nil?
-
response_mappings.each {|response_mapping|
-
response_mapping.delete
-
}
-
end
-
return "Automatic meta reviewer assignment failed! Please try again with different number of reviews." + exc.message
-
# include "#{exc.message}" to the above message to find what the error was.."
-
end
-
-
-
end
-
-
end
-
1
module ExportFileHelper
-
end
-
1
module FileHelper
-
-
1
def self.sanitize_filename(file_name)
-
just_filename = File.basename(file_name)
-
FileHelper.clean_path(just_filename)
-
end
-
-
1
def self.move_file(oldloc, newloc)
-
items = newloc.split(/\//)
-
filename = items[items.length-1]
-
items.delete_at(items.length-1)
-
-
newdir = String.new
-
items.each{
-
| item |
-
newdir += FileHelper::clean_path(item)+"/"
-
}
-
-
FileHelper::create_directory_from_path(newdir)
-
FileUtils.mv oldloc, newdir+filename
-
end
-
-
1
def self.update_file_location(oldpath,newpath)
-
begin
-
if oldpath and newpath
-
create_directory_from_path(newpath)
-
oldcontents = Dir.glob(oldpath + "/*")
-
FileUtils.mv(oldcontents,newpath)
-
FileUtils.remove_dir(oldpath)
-
elsif newpath # nil oldpath
-
create_directory_from_path(newpath)
-
end
-
rescue
-
puts $!
-
end
-
end
-
-
# replace invalid characters with underscore
-
# valid: period
-
# underscore
-
# forward slash
-
# alphanumeric characters
-
1
def self.clean_path(file_name)
-
newstr = file_name.gsub(/[^\w\.\_\/]/,'_')
-
newstr.gsub("'","_")
-
end
-
-
-
1
def self.sanitize_folder(folder)
-
folder.gsub("..","")
-
end
-
-
1
def self.delete_directory(in_object)
-
begin
-
entries = Dir.entries(in_object.get_path)
-
if entries and entries.size == 2
-
FileUtils.remove_dir(in_object.get_path)
-
end
-
rescue PathError
-
# No action required
-
rescue
-
raise "An error was encountered while deleting the directory: "+$!
-
end
-
end
-
-
1
def self.create_directory(in_object)
-
begin
-
if !File.exists? in_object.get_path
-
FileUtils.mkdir_p(in_object.get_path)
-
end
-
rescue PathError
-
puts $!
-
rescue
-
puts $!
-
raise "An error was encountered while creating this directory: "+$!
-
end
-
end
-
-
1
def self.create_directory_from_path(path)
-
begin
-
if !File.exists? path
-
FileUtils.mkdir_p(path)
-
end
-
rescue PathError
-
puts $!
-
rescue
-
puts $!
-
raise "An error was encountered while creating this directory: "+$!
-
end
-
end
-
end
-
1
module GradesHelper
-
-
# Render the accordian title
-
1
def get_accordion_title(last_topic, new_topic)
-
if last_topic.eql? nil
-
#this is the first accordion
-
render :partial => "response/accordion", :locals => {:title => new_topic, :is_first => true}
-
-
elsif !new_topic.eql? last_topic
-
#render new accordion
-
render :partial => "response/accordion", :locals => {:title => new_topic, :is_first => false}
-
-
end
-
end
-
-
# Render the table to display the question, score and response
-
1
def construct_table(parameters)
-
table_hash = {"table_title" => nil, "table_headers" => nil, "start_table" => false, "start_col" => false, "end_col" => false, "end_table" => false}
-
-
#we need to check if these parameters use tables
-
parameters = parameters.last(3)
-
if parameters[2].nil?
-
return table_hash
-
end
-
current_ques = parameters[2].split("|")[0]
-
total_col_ques = parameters[2].split("|")[1]
-
current_col = parameters[2].split("|")[2]
-
total_col = parameters[2].split("|")[3]
-
-
#since it's first item in a column we need to start a new column
-
if current_ques.to_i == 1
-
table_hash["start_col"] = true
-
#if it's the first column we need to send the title and headers
-
if current_col.to_i == 1
-
if parameters[0].length > 0
-
table_hash["table_title"] = parameters[0]
-
end
-
table_hash["start_table"] = true
-
if parameters[1].length > 0
-
table_hash["table_headers"] = parameters[1]
-
end
-
end
-
end
-
#end of column, we need to close column
-
if current_ques == total_col_ques
-
table_hash["end_col"] = true
-
#end of table we need to close table
-
if total_col == current_col
-
table_hash["end_table"] = true
-
end
-
end
-
table_hash
-
end
-
-
# Render the question, score and response and set default parameters
-
1
def find_question_type(question, ques_type, q_number, is_view, file_url, score, score_range)
-
default_textfield_size = "3"
-
default_textarea_size = "40x5"
-
default_dropdown = ["Edit Rubric", "No Values"]
-
-
#refactored code
-
q_parameter = ques_type.parameters.split("::")
-
table_hash = construct_table(q_parameter)
-
view_output = nil
-
if is_view
-
view_output = "No Response"
-
if !score.comments.nil?
-
view_output = score.comments
-
end
-
end
-
-
-
# Render appropriate control for each question type
-
case ques_type.q_type
-
when "Checkbox"
-
if is_view
-
view_output = "<img src=\"/images/delete_icon.png\">" + question.txt + "<br/>"
-
if score.comments == "1"
-
view_output = "<img src=\"/images/Check-icon.png\">" + question.txt + "<br/>"
-
end
-
end
-
param1 = "response/checkbox"
-
param2 = {:ques_num => q_number, :ques_text => question.txt, :table_title => table_hash["table_title"], :table_headers => table_hash["table_headers"], :start_col => table_hash["start_col"], :start_table => table_hash["start_table"], :end_col => table_hash["end_col"], :end_table => table_hash["end_table"], :view => view_output}
-
render_ui(param1,param2)
-
when "TextField"
-
-
#look for size parameters
-
size = default_textfield_size
-
if !q_parameter[1].nil? && q_parameter[1].length > 0
-
size = q_parameter[1]
-
end
-
-
#look for inline and separator parameters
-
separator = nil
-
is_first = false
-
is_last = false
-
if !q_parameter[2].nil?
-
separator = q_parameter[2].split("|")[q_parameter[3].split("|")[0].to_i - 1]
-
if q_parameter[3].split("|")[0].to_i == 1
-
is_first = true
-
elsif q_parameter[3].split("|")[0] == q_parameter[3].split("|")[1]
-
is_last = true
-
end
-
end
-
param1 = "response/textfield"
-
param2 = {:ques_num => q_number, :field_size => size, :ques_text => question.txt, :separator => separator, :isFirst => is_first, :isLast => is_last, :view => view_output}
-
render_ui(param1,param2)
-
when "TextArea"
-
-
#look for size parameters
-
size = default_textarea_size
-
if !q_parameter[1].nil? && q_parameter[1].length > 0
-
size = q_parameter[1]
-
end
-
-
param1 = "response/textarea"
-
param2 = {:ques_num => q_number, :area_size => size, :ques_text => question.txt, :table_title => table_hash["table_title"], :table_headers => table_hash["table_headers"], :start_col => table_hash["start_col"], :start_table => table_hash["start_table"], :end_col => table_hash["end_col"], :end_table => table_hash["end_table"], :view => view_output}
-
render_ui(param1,param2)
-
-
when "UploadFile"
-
-
#check to see if rendering view
-
if is_view
-
view_output = "File has not been uploaded"
-
if !file_url.nil?
-
view_output = file_url.to_s
-
end
-
end
-
param1 = "response/fileUpload"
-
param2 = {:ques_num => q_number, :ques_text => question.txt, :view => view_output}
-
render_ui(param1,param2)
-
when "DropDown"
-
-
#look for dropdown values
-
dd_values = default_dropdown
-
if !q_parameter[1].nil? && q_parameter[1].length > 0
-
dd_values = q_parameter[1].split("|")
-
end
-
param1 = "response/dropdown"
-
param2 = {:ques_num => q_number, :ques_text => question.txt, :options => dd_values, :table_title => table_hash["table_title"], :table_headers => table_hash["table_headers"], :start_col => table_hash["start_col"], :start_table => table_hash["start_table"], :end_col => table_hash["end_col"], :end_table => table_hash["end_table"], :view => view_output}
-
render_ui(param1,param2)
-
when "Rating"
-
if !q_parameter[1].nil? && q_parameter[1].length > 0
-
curr_ques = q_parameter[1].split("|")[0]
-
end
-
-
if curr_ques == 2
-
param1 = "response/textarea"
-
param2 = {:ques_num => q_number, :area_size => default_textarea_size, :ques_text => question.txt, :table_title => table_hash["table_title"], :table_headers => table_hash["table_headers"], :start_col => table_hash["start_col"], :start_table => table_hash["start_table"], :end_col => table_hash["end_col"], :end_table => table_hash["end_table"], :view => view_output}
-
-
else
-
param1 = "response/dropdown"
-
param2 = {:ques_num => q_number, :ques_text => question.txt, :options => score_range, :table_title => table_hash["table_title"], :table_headers => table_hash["table_headers"], :start_col => table_hash["start_col"], :start_table => table_hash["start_table"], :end_col => table_hash["end_col"], :end_table => table_hash["end_table"], :view => view_output}
-
-
end
-
render_ui(param1,param2)
-
end
-
end
-
1
def render_ui(param1,param2)
-
render :partial => param1,:locals =>param2
-
end
-
end
-
1
module ImpersonateHelper
-
end
-
1
require 'csv'
-
-
1
module ImportFileHelper
-
-
1
def self.define_attributes(row)
-
attributes = {}
-
attributes["role_id"] = Role.student.id
-
attributes["name"] = row[0].strip
-
attributes["fullname"] = row[1]
-
attributes["email"] = row[2].strip
-
attributes["password"] = row[3].strip
-
attributes["password_confirmation"] = attributes["password"]
-
attributes["email_on_submission"] = 1
-
attributes["email_on_review"] = 1
-
attributes["email_on_review_of_review"] = 1
-
attributes
-
end
-
-
1
def self.create_new_user(attributes, session)
-
user = User.new(attributes)
-
user.parent_id = (session[:user]).id
-
user.save!
-
-
user
-
end
-
end
-
-
-
1
require 'csv'
-
-
1
module ImportTopicsHelper
-
-
1
def self.define_attributes(row)
-
attributes = {}
-
attributes["topic_identifier"] = row[0].strip
-
attributes["topic_name"] = row[1].strip
-
attributes["max_choosers"] = row[2]
-
attributes["category"] = row[3].strip
-
attributes
-
end
-
-
1
def self.create_new_sign_up_topic(attributes, session)
-
sign_up_topic = SignUpTopic.new(attributes)
-
sign_up_topic.assignment_id = session[:assignment_id]
-
sign_up_topic.save
-
#sign_up_topic
-
end
-
end
-
-
-
1
module InstitutionHelper
-
end
-
1
module InvitationHelper
-
end
-
1
module JoinTeamRequestsHelper
-
end
-
1
module LeaderboardHelper
-
-
# This method gets the name for a course. If the course id
-
# provided is 0, that indicates an assignment that is not
-
# associated with a course, and the course name provided
-
# is "Unaffiliated Assignments"
-
1
def self.getCourseName(courseID)
-
if courseID == 0
-
courseName = "Unaffiliated Assignments"
-
else
-
courseName = Course.find(courseID).name
-
end
-
courseName
-
end
-
-
# This method converts the questionnaire_type to a
-
# sensible string for the Leaderboard table.
-
1
def self.getAchieveName(qtype)
-
achieveName = Leaderboard.find(:first , :conditions =>[ "qtype like ?",qtype]).name
-
-
end
-
-
# This method gets the name for an assignment. If for some unexpected
-
# reason the assignment id does not exist, the string "Unnamed Assignment"
-
# is returned.
-
1
def self.getAssignmentName(assignmentID)
-
if !assignmentID or assignmentID == 0
-
assignmentName = "Unnamed Assignment"
-
else
-
assignmentName = Assignment.find(assignmentID).name
-
end
-
assignmentName
-
end
-
-
# Get the name of the user, honoring the privacy settings.
-
# If the requesterID and userID are the same (the student querying is
-
# the person on the leaderboard), a "You!" is displayed.
-
# If the requesterID is a TA, instructor, or admin, the privacy
-
# setting is disregarded.
-
1
def self.getUserName(requesterID, userID)
-
user = User.find(userID)
-
instructor = userIsInstructor?(requesterID)
-
if user.leaderboard_privacy and requesterID != userID and !instructor
-
userName = "*****"
-
elsif requesterID == userID
-
userName = "You!"
-
else
-
userName = user.fullname
-
end
-
end
-
-
# Identify whether user is considered instructor
-
1
def self.userIsInstructor?(userID)
-
# For now, we'll consider Instructors, Admins, Super-Admins, and TAs as instructors
-
instructorRoles = Array.new
-
instructorRoles << Role.find_by_name("Instructor").id
-
instructorRoles << Role.find_by_name("Administrator").id
-
instructorRoles << Role.find_by_name("Super-Administrator").id
-
instructorRoles << Role.find_by_name("Teaching Assistant").id
-
user = User.find(userID)
-
instructor = false
-
if instructorRoles.index(user.role_id)
-
instructor = true
-
end
-
instructor
-
end
-
-
# Returns list of course ids in which the student has an assignment
-
1
def self.studentInWhichCourses(userid)
-
# Get all entries in Participant table for user
-
assignPartList = AssignmentParticipant.find(:all, :conditions =>["user_id =?",userid])
-
@courseList = Array.new
-
-
for participantEntry in assignPartList
-
-
## get the ass in quesstion, get the course in question
-
assgt = Assignment.find(participantEntry.parent_id)
-
if assgt.course_id == nil
-
@courseList << 0
-
else
-
@courseList << assgt.course_id
-
end
-
end
-
-
@courseList.uniq!
-
-
@courseList
-
end
-
-
# This methods gets all the courses that an instructor has been assigned.
-
# This method assumes the instructor_id in the Courses table indicates
-
# the courses an instructor is managing.
-
1
def self.instructorCourses(userid)
-
courseTuples = Course.find(:all,
-
:conditions => ['instructor_id = ?', userid])
-
-
@courseList = Array.new
-
courseTuples.each { |course| @courseList << course.id }
-
@courseList
-
end
-
-
# This method gets the display data needed to show the Top 3 leaderboard
-
1
def self.getTop3Leaderboards(userid, assignmentid)
-
courseList = LeaderboardHelper.studentInWhichCourses(userid)
-
csHash = Leaderboard.getParticipantEntriesInAssignment(assignmentid)
-
csHash = Leaderboard.sortHash(csHash)
-
-
# Setup top 3 leaderboards for easier consumption by view
-
top3LeaderBoards = Array.new
-
csHash.each_pair{|qtype, courseHash|
-
courseHash.each_pair{|course, userGradeArray|
-
assignmentName = LeaderboardHelper.getAssignmentName(assignmentid)
-
achieveName = LeaderboardHelper.getAchieveName(qtype)
-
leaderboardHash = Hash.new
-
leaderboardHash = {:achievement => achieveName,
-
:courseName => assignmentName,
-
:sortedGrades => userGradeArray}
-
top3LeaderBoards << leaderboardHash
-
}
-
}
-
top3LeaderBoards
-
end
-
-
# This method is only provided for diagnostic purposes. It can be executed from
-
# script/console to see what's in the Computed Scores table, in case there is
-
# a concern about accuracy of leaderboard results.
-
1
def self.dumpCSTable
-
@expList = Array.new
-
@csEntries = ComputedScore.find(:all)
-
@csEntries.each { |csEntry|
-
participant = AssignmentParticipant.find(csEntry.participant_id)
-
questionnaire = Questionnaire.find(csEntry.questionnaire_id)
-
-
@expList << {:userName => participant.user.name,
-
:assignName => participant.assignment.name,
-
:courseID => participant.assignment.course.id,
-
:instructorName => questionnaire.instructor.name,
-
:qtypeName => questionnaire.qtype,
-
:totalScore => csEntry.total_score}
-
}
-
@expList
-
end
-
-
end
-
1
module MailerHelper
-
1
def self.send_mail_to_user(user,subject,partial_name,password)
-
8
Mailer.generic_message ({
-
:to => user.email,
-
:subject => subject,
-
:body => {
-
:user => user,
-
:password => password,
-
:first_name => ApplicationHelper::get_user_first_name(user),
-
:partial_name => partial_name
-
}
-
})
-
end
-
end
-
# This helper contains all functions associated with team management.
-
# These include creating a new team, adding a new member to a team etc
-
# This helper is used by both sign_up_sheet controller and signup controller
-
1
module ManageTeamHelper
-
-
# Adds a user specified bu 'user' object to a team specified by 'team_id'
-
1
def create_team_users(user, team_id)
-
#if user does not exist flash message
-
if !user
-
urlCreate = url_for :controller => 'users', :action => 'new'
-
flash[:error] = "\"#{params[:user][:name].strip}\" is not defined. Please <a href=\"#{urlCreate}\">create</a> this user before continuing."
-
end
-
#find the team with 'team_id' form database and add new user to team
-
team = Team.find(team_id)
-
team.add_member(user, team.parent_id)
-
end
-
#check if the user specified by 'user' already belongs to team specified by 'team_id'
-
1
def has_user(user, team_id)
-
if TeamsUser.find_by_team_id_and_user_id(team_id, user.id)
-
return true
-
else
-
return false
-
end
-
end
-
-
end
-
1
module ParticipantsHelper
-
-
#separates the file into the necessary elements to create a new user
-
1
def self.upload_users(filename, session, params, home_page)
-
users = Array.new
-
File.open(filename, "r") do |infile|
-
while (rline = infile.gets)
-
config = get_config()
-
attributes = define_attributes(rline.split(config["dlm"]),config)
-
users << define_user(attributes, session, params, home_page)
-
end
-
end
-
return users
-
end
-
-
1
def self.define_attributes(line_split, config)
-
attributes = {}
-
attributes["role_id"] = Role.find_by_name "Student"
-
attributes["name"] = line_split[config["name"].to_i]
-
attributes["fullname"] = config["fullname"]
-
attributes["email"] = line_split[config["email"].to_i]
-
attributes["password"] = assign_password(8)
-
attributes["email_on_submission"] = 1
-
attributes["email_on_review"] = 1
-
attributes["email_on_review_of_review"] = 1
-
attributes
-
end
-
-
1
def self.define_user(attrs, session, params, home_page)
-
user = User.find_by_name(attrs["name"])
-
if user == nil
-
user = create_new_user(attrs, session)
-
end
-
if (params[:course_id] != nil)
-
participant = add_user_to_course(params, user)
-
elsif (params[:assignment_id] != nil)
-
participant = add_user_to_assignment(params, user)
-
end
-
if participant != nil
-
participant.email(attrs["password"], home_page)
-
end
-
return user
-
end
-
-
1
def self.create_new_user(attrs, session)
-
user = User.new
-
user.update_attributes attrs
-
user.parent_id = (session[:user]).id
-
user.save
-
user
-
end
-
-
1
def self.add_user_to_assignment(params, user)
-
assignment = Assignment.find params[:assignment_id]
-
if (AssignmentParticipant.find(:all,{:conditions => ['user_id=? AND parent_id=?', user.id, assignment.id]}).size == 0)
-
return AssignmentParticipant.create(:parent_id => assignment.id, :user_id => user.id)
-
end
-
end
-
-
1
def self.add_user_to_course(params, user)
-
if (CourseParticipant.find(:all, {:conditions => ['user_id=? AND parent_id=?', user.id, params[:course_id]]}).size == 0)
-
CourseParticipant.create(:user_id => user.id, :parent_id => params[:course_id])
-
end
-
end
-
-
1
def self.get_config
-
config = {}
-
cfgdir = RAILS_ROOT + "/config/"
-
File.open(cfgdir+"roster_config", "r") do |infile|
-
while (line = infile.gets)
-
store_item(line,"dlm",config)
-
store_item(line,"name",config)
-
store_item(line,"fullname",config)
-
store_item(line,"email",config)
-
end
-
end
-
return config
-
end
-
-
1
def self.store_item(line, ident, config)
-
line_split = line.split("=")
-
if line_split[0] == ident
-
newstr = line_split[1].sub!("\n","")
-
if newstr != nil
-
config[ident] = newstr.strip
-
end
-
end
-
end
-
-
end
-
1
module PasswordRetrievalHelper
-
end
-
1
module PgUsersHelper
-
end
-
1
module ProfileHelper
-
end
-
1
module PublishingHelper
-
end
-
1
module QuestionTypesHelper
-
end
-
1
require 'fastercsv'
-
1
require 'csv'
-
-
1
module QuestionnaireHelper
-
-
1
CSV_QUESTION = 0
-
1
CSV_TYPE = 1
-
1
CSV_PARAM = 2
-
1
CSV_WEIGHT = 3
-
-
1
def self.create_questionnaire_csv(questionnaire, user_name)
-
csv_data = FasterCSV.generate do |csv|
-
for question in questionnaire.questions
-
# Each row is formatted as follows
-
# Question, question advice (from high score to low), type, weight
-
row = Array.new
-
row << question.txt
-
if questionnaire.section != "Custom"
-
row << "True/False" if question.true_false
-
row << "Numeric" if !question.true_false
-
else
-
row << QuestionType.find_by_question_id(question.id).q_type
-
end
-
-
row << question.question_type.try(:parameters) || ''
-
-
row << question.weight
-
-
#if questionnaire.section == "Custom"
-
# row << QuestionType.find_by_question_id(question.id).parameters
-
#else
-
# row << ""
-
#end
-
-
# loop through all the question advice from highest score to lowest score
-
adjust_advice_size(questionnaire, question)
-
for advice in question.question_advices.sort {|x,y| y.score <=> x.score }
-
row << advice.advice
-
end
-
-
csv << row
-
end
-
end
-
-
return csv_data
-
end
-
-
1
def self.get_questions_from_csv(questionnaire, file)
-
questions = Array.new
-
custom_rubric = questionnaire.section == "Custom"
-
-
CSV::Reader.parse(file) do |row|
-
if row.length > 0
-
i = 0
-
score = questionnaire.max_question_score
-
q = Question.new
-
-
q_type = QuestionType.new if custom_rubric
-
-
q.true_false = false
-
-
row.each do |cell|
-
case i
-
when CSV_QUESTION
-
q.txt = cell.strip if cell != nil
-
when CSV_TYPE
-
if cell != nil
-
q.true_false = cell.downcase.strip == Question::TRUE_FALSE.downcase
-
q_type.q_type = cell.strip if custom_rubric
-
end
-
when CSV_PARAM
-
if custom_rubric
-
q_type.parameters = cell.strip if cell
-
end
-
when CSV_WEIGHT
-
q.weight = cell.strip.to_i if cell
-
else
-
if score >= questionnaire.min_question_score and cell != nil
-
a = QuestionAdvice.new(:score => score, :advice => cell.strip) if custom_rubric
-
a = QuestionAdvice.new(:score => questionnaire.min_question_score + i - 4, :advice => cell.strip)
-
score = score - 1
-
q.question_advices << a
-
end
-
end
-
-
i = i + 1
-
end
-
-
q.save
-
-
q_type.question = q if custom_rubric
-
q_type.save if custom_rubric
-
-
questions << q
-
end
-
end
-
-
questions
-
end
-
-
1
def self.adjust_advice_size(questionnaire, question)
-
if question.true_false and question.question_advices.length != 2
-
question.question_advices << QuestionAdvice.new(:score=>0)
-
question.question_advices << QuestionAdvice.new(:score=>1)
-
-
QuestionAdvice.delete_all(["question_id = ? AND (score > 1 OR score < 0)", question.id])
-
return true
-
elsif question.true_false == false
-
for i in (questionnaire.min_question_score..questionnaire.max_question_score)
-
print "\n#{i}: #{question.id}"
-
qa = QuestionAdvice.find(:first,
-
:conditions=>"question_id = #{question.id} AND score = #{i}")
-
-
if qa == nil
-
print " NEW "
-
question.question_advices << QuestionAdvice.new(:score=>i)
-
end
-
end
-
-
QuestionAdvice.delete_all(["question_id = ? AND (score > ? OR score < ?)",
-
question.id, questionnaire.max_question_score, questionnaire.min_question_score])
-
return true
-
end
-
-
return false
-
end
-
end
-
1
module ReportsHelper
-
end
-
1
module ResponseHelper
-
-
# Compute the currently awarded scores for the reviewee
-
# If the new teammate review's score is greater than or less than
-
# the existing scores by a given percentage (defined by
-
# the instructor) then notify the instructor.
-
# ajbudlon, nov 18, 2008
-
1
def self.compare_scores(new_response, questionnaire)
-
map_class = new_response.map.class
-
existing_responses = map_class.get_assessments_for(new_response.map.reviewee)
-
total, count = get_total_scores(existing_responses,new_response)
-
if count > 0
-
notify_instructor(new_response.map.assignment, new_response, questionnaire, total, count)
-
end
-
end
-
-
# Compute the scores previously awarded to the recipient
-
# ajbudlon, nov 18, 2008
-
1
def self.get_total_scores(item_list,curr_item)
-
total = 0
-
count = 0
-
item_list.each {
-
| item |
-
if item.id != curr_item.id
-
count += 1
-
total += item.get_total_score
-
end
-
}
-
return total,count
-
end
-
-
# determine if the instructor should be notified
-
# ajbudlon, nov 18, 2008
-
1
def self.notify_instructor(assignment,curr_item,questionnaire,total,count)
-
max_possible_score, weights = assignment.get_max_score_possible(questionnaire)
-
new_score = curr_item.get_total_score.to_f*weights
-
existing_score = (total.to_f/count).to_f*weights
-
-
aq = AssignmentQuestionnaire.find_by_user_id_and_assignment_id_and_questionnaire_id(assignment.instructor_id, assignment.id, questionnaire.id)
-
-
unless aq
-
aq = AssignmentQuestionnaire.find_by_user_id_and_assignment_id_and_questionnaire_id(assignment.instructor_id, nil, nil)
-
end
-
-
if aq
-
allowed_difference = max_possible_score.to_f * aq.notification_limit / 100
-
if new_score < (existing_score - allowed_difference) or new_score > (existing_score + allowed_difference)
-
new_pct = new_score.to_f/max_possible_score
-
avg_pct = existing_score.to_f/max_possible_score
-
curr_item.notify_on_difference(new_pct,avg_pct,aq.notification_limit)
-
end
-
end
-
end
-
-
1
def label(object_name, method, label)
-
content_tag(:label, h(label), :for => "#{object_name}_#{method}")
-
end
-
-
1
def remove_empty_advice(advices)
-
filtered_advices = Array.new
-
advices.each { | advice |
-
if advice.advice.to_s != ""
-
filtered_advices << advice
-
end
-
}
-
filtered_advices
-
end
-
-
1
def get_accordion_title(last_topic, new_topic)
-
if last_topic.eql? nil
-
#this is the first accordion
-
render :partial => "response/accordion", :locals => {:title => new_topic, :is_first => true}
-
elsif !new_topic.eql? last_topic
-
#render new accordion
-
render :partial => "response/accordion", :locals => {:title => new_topic, :is_first => false}
-
end
-
end
-
-
1
def construct_table(parameters)
-
table_hash = {"table_title" => nil, "table_headers" => nil, "start_table" => false, "start_col" => false, "end_col" => false, "end_table" => false}
-
-
#we need to check if these parameters use tables
-
parameters = parameters.last(3)
-
if parameters[2].nil?
-
return table_hash
-
end
-
current_ques = parameters[2].split("|")[0]
-
total_col_ques = parameters[2].split("|")[1]
-
current_col = parameters[2].split("|")[2]
-
total_col = parameters[2].split("|")[3]
-
-
#since it's first item in a column we need to start a new column
-
if current_ques.to_i == 1
-
table_hash["start_col"] = true
-
#if it's the first column we need to send the title and headers
-
if current_col.to_i == 1
-
if parameters[0].length > 0
-
table_hash["table_title"] = parameters[0]
-
end
-
table_hash["start_table"] = true
-
if parameters[1].length > 0
-
table_hash["table_headers"] = parameters[1]
-
end
-
end
-
end
-
#end of column, we need to close column
-
if current_ques == total_col_ques
-
table_hash["end_col"] = true
-
#end of table we need to close table
-
if total_col == current_col
-
table_hash["end_table"] = true
-
end
-
end
-
table_hash
-
end
-
-
1
def find_question_type(question, ques_type, q_number, is_view, file_url, score, score_range)
-
default_textfield_size = "3"
-
default_textarea_size = "40x5"
-
default_dropdown = ["Edit Rubric", "No Values"]
-
-
case ques_type.q_type
-
when "Checkbox"
-
#Parameters
-
#section::tableTitle::tableHeader1|tableHeader2::curr_col_ques|total_col_ques|curr_col|max_cols
-
-
#look for table parameters
-
table_hash = construct_table(ques_type.parameters.split("::"))
-
-
#check to see if rendering view
-
view_output = nil
-
if is_view
-
view_output = "<img src=\"/images/delete_icon.png\">" + question.txt + "<br/>"
-
if @review_scores && @review_scores[q_number].comments == "1"
-
view_output = "<img src=\"/images/Check-icon.png\">" + question.txt + "<br/>"
-
end
-
end
-
-
render :partial => "response/checkbox", :locals => {:ques_num => q_number, :ques_text => question.txt, :table_title => table_hash["table_title"], :table_headers => table_hash["table_headers"], :start_col => table_hash["start_col"], :start_table => table_hash["start_table"], :end_col => table_hash["end_col"], :end_table => table_hash["end_table"], :view => view_output}
-
when "TextField"
-
#Parameters
-
#section::size::separator1|separator2::curr_ques|max_ques
-
q_parameter = ques_type.parameters.split("::")
-
-
#look for size parameters
-
size = default_textfield_size
-
if !q_parameter[1].nil? && q_parameter[1].length > 0
-
size = q_parameter[1]
-
end
-
-
#look for inline and separator parameters
-
separator = nil
-
is_first = false
-
is_last = false
-
if !q_parameter[2].nil?
-
separator = q_parameter[2].split("|")[q_parameter[3].split("|")[0].to_i - 1]
-
if q_parameter[3].split("|")[0].to_i == 1
-
is_first = true
-
elsif q_parameter[3].split("|")[0] == q_parameter[3].split("|")[1]
-
is_last = true
-
end
-
end
-
-
#check to see if rendering view
-
view_output = nil
-
if is_view
-
view_output = "No Response"
-
if @review_scores && !@review_scores[q_number].comments.nil?
-
view_output = @review_scores[q_number].comments
-
end
-
end
-
-
render :partial => "response/textfield", :locals => {:ques_num => q_number, :field_size => size, :ques_text => question.txt, :separator => separator, :isFirst => is_first, :isLast => is_last, :view => view_output}
-
when "TextArea"
-
#Parameters
-
#section::size::tableTitle::tableHeader1|tableHeader2::curr_col_ques|total_col_ques|curr_col|max_cols
-
q_parameter = ques_type.parameters.split("::")
-
-
#look for size parameters
-
size = default_textarea_size
-
if !q_parameter[1].nil? && q_parameter[1].length > 0
-
size = q_parameter[1]
-
end
-
-
#look for table parameters
-
table_hash = construct_table(q_parameter)
-
-
#check to see if rendering view
-
view_output = nil
-
if is_view
-
view_output = "No Response"
-
if @review_scores && !@review_scores[q_number].comments.nil?
-
view_output = @review_scores[q_number].comments
-
end
-
end
-
-
render :partial => "response/textarea", :locals => {:ques_num => q_number, :area_size => size, :ques_text => question.txt, :table_title => table_hash["table_title"], :table_headers => table_hash["table_headers"], :start_col => table_hash["start_col"], :start_table => table_hash["start_table"], :end_col => table_hash["end_col"], :end_table => table_hash["end_table"], :view => view_output}
-
when "UploadFile"
-
#Parameters
-
#section
-
-
#check to see if rendering view
-
view_output = nil
-
if is_view
-
view_output = "File has not been uploaded"
-
if !file_url.nil?
-
view_output = file_url.to_s
-
end
-
end
-
-
render :partial => "response/fileUpload", :locals => {:ques_num => q_number, :ques_text => question.txt, :view => view_output}
-
when "DropDown"
-
#Parameters
-
#section::ddValue1|ddValue2::tableTitle::tableHeader1|tableHeader2::curr_col_ques|total_col_ques|curr_col|max_cols
-
q_parameter = ques_type.parameters.split("::")
-
-
#look for dropdown values
-
dd_values = default_dropdown
-
if !q_parameter[1].nil? && q_parameter[1].length > 0
-
dd_values = q_parameter[1].split("|")
-
end
-
-
#look for table parameters
-
table_hash = construct_table(q_parameter)
-
-
#check to see if rendering view
-
view_output = nil
-
if is_view
-
view_output = "No Response"
-
if !@review_scores[q_number].comments.nil?
-
view_output = @review_scores[q_number].comments
-
end
-
end
-
-
render :partial => "response/dropdown", :locals => {:ques_num => q_number, :ques_text => question.txt, :options => dd_values, :table_title => table_hash["table_title"], :table_headers => table_hash["table_headers"], :start_col => table_hash["start_col"], :start_table => table_hash["start_table"], :end_col => table_hash["end_col"], :end_table => table_hash["end_table"], :view => view_output}
-
when "Rating"
-
#Parameters
-
#section::currQues|2
-
-
q_parameter = ques_type.parameters.split("::")
-
-
#get current question
-
if !q_parameter[1].nil? && q_parameter[1].length > 0
-
curr_ques = q_parameter[1].split("|")[0]
-
end
-
-
#check to see if rendering view
-
view_output = nil
-
if curr_ques == "2"
-
if is_view
-
view_output = "No Response"
-
if @review_scores && !@review_scores[q_number].comments.nil?
-
view_output = @review_scores[q_number].comments
-
end
-
end
-
render :partial => "response/textarea", :locals => {:ques_num => q_number, :area_size => default_textarea_size, :ques_text => question.txt, :table_title => nil, :table_headers => nil, :start_col => nil, :start_table => nil, :end_col => nil, :end_table => nil, :view => view_output}
-
else
-
if is_view
-
view_output = "No Response"
-
if !@review_scores[q_number].try(:comments)
-
view_output = @review_scores[q_number].comments
-
end
-
end
-
render :partial => "response/dropdown", :locals => {:ques_num => q_number, :ques_text => question.txt, :options => score_range, :table_title => nil, :table_headers => nil, :start_col => nil, :start_table => nil, :end_col => nil, :end_table => nil, :view => view_output}
-
end
-
end
-
end
-
end
-
1
module ReviewCommentsHelper
-
-
1
def self.construct_comments_table(comment_array)
-
return "" unless comment_array.length > 0
-
-
comment_window_html = "<table width='100%' cellpadding='3' style='table-layout: fixed; word-wrap: break-word;'>"
-
for i in 0..(comment_array.length-1) do
-
comment_window_html += "<tr><td><b>Comment #{i+1}:</b><br/>" +
-
comment_array[i].to_s + "</td></tr>"
-
end
-
comment_window_html += "</table>"
-
return comment_window_html
-
end
-
-
-
end
-
1
module ReviewFilesHelper
-
1
CODE_REVIEW_DIR_SUFFIX = '_code_review_files'
-
1
VERSION_DIR_SUFFIX = 'version_'
-
-
# Removes invalid chars (valid are period, underscore, forward_slash,
-
# alphanumeric characters). Replaces whitespace with underscore. Returns only
-
# the base filename (minus the directory e.g. /dir1/dir2/abc.rb => abc.rb)
-
1
def self.get_safe_filename(filename)
-
safe_filename = filename.gsub(/\\/,"/")
-
safe_filename = FileHelper::sanitize_filename(safe_filename) # returns only the filename -- sanitized (but has whitespace)
-
safe_filename = File.split(safe_filename).last.gsub(" ",'_')
-
return safe_filename
-
end
-
-
# Returns the type (extension) of the file.
-
1
def self.get_file_type file_name
-
base = File.basename(file_name)
-
if base.split(".").size > 1
-
return base.split(".")[base.split(".").size-1]
-
end
-
end
-
-
# Calculate version directory
-
1
def self.get_version_directory(participant, version_number)
-
return participant.get_path.to_s + CODE_REVIEW_DIR_SUFFIX + '/' +
-
VERSION_DIR_SUFFIX + version_number.to_s + '/'
-
end
-
-
# Calculate code review file directory
-
1
def self.get_code_review_file_dir(participant)
-
return participant.get_path.to_s + CODE_REVIEW_DIR_SUFFIX + '/'
-
end
-
-
-
-
end
-
-
1
module ReviewingHelper
-
end
-
1
module SignupHelper
-
end
-
1
module StudentReviewHelper
-
end
-
1
module StudentTaskHelper
-
end
-
1
module StudentTeamHelper
-
end
-
1
module SubmissionHelper
-
end
-
1
module SubmittedContentHelper
-
-
1
def display_directory_tree(participant, files, flag)
-
index = 0
-
participant = @participant if @participant # TODO: Verify why this is needed
-
assignment = participant.assignment # participant is @map.contributor
-
topic_id = participant.topic_id # participant is @map.reviewer
-
check_stage = assignment.get_current_stage(topic_id)
-
-
ret = "\n<table id='file_table' cellspacing='5'>"
-
ret += "\n <tr><th>Name</th><th>Size</th><th>Type</th><th>Date Modified</th></tr>"
-
for file in files
-
ret += "\n <tr>"
-
ret += "\n <td valign = top>\n "
-
if check_stage != "Complete" && flag == false
-
ret += "<input type=radio id='chk_files' name='chk_files' value='#{index}'>"
-
else
-
ret += "<b>**</b> ";
-
end
-
ret += "\n <input type=hidden id='filenames_#{index}' name='filenames[#{index}]' value='#{File.basename(file)}'>"
-
ret += "\n <input type=hidden id='directories_#{index}' name='directories[#{index}]' value='#{File.dirname(file)}'>"
-
if File.directory?(file)
-
#ret += "\n <a title='Expand/Collapse' href='#' onclick='javascript:collapseSubDirectory(#{index}); return false;'><img id='expand.#{index}' alt='Expand/Collapse' title='Expand/Collapse' src='/images/up.png'></a> "
-
ret += link_to File.basename(file), :controller => 'submitted_content', :action => 'edit', :id => participant.id, "current_folder[name]" => file
-
#ret += list_sub_directories(file, participant)
-
else
-
ret += "\n "
-
parentFolder = File.dirname(file)
-
if parentFolder != participant.get_path
-
parentFolder.sub!(participant.get_path+"/","")
-
parentFolder += "/"
-
else
-
parentFolder = ""
-
end
-
-
location = parentFolder + File.basename(file)
-
ret += link_to location, :controller => 'submitted_content', :action => 'download', :id => participant.id, :download => File.basename(file), "current_folder[name]" => File.dirname(file)
-
end
-
ret += "\n </td>\n <td valign = top>\n"
-
ret += File.size(file).to_s
-
ret += "\n </td>\n <td valign = top>\n"
-
ret += File.ftype(file)
-
ret += "\n </td>\n <td valign = top>\n"
-
ret += File.mtime(file).to_s
-
ret += "\n </td>\n </tr>"
-
index += 1
-
end
-
ret += "\n</table>"
-
return ret
-
end
-
-
1
def list_sub_directories (file, participant)
-
index = 0
-
ret = "<ul id= 'subdir."+index.to_s+"."+index.to_s+"'>"
-
Dir.foreach( file ) {|path|
-
next if path == "." or path == ".." or path == ".svn"
-
index += 1
-
disp = file + "/" + path
-
display = File.basename(file) +"/"+ path
-
ret += "<li>"
-
if @check_stage != "Complete" && @flag == false
-
ret += "<input type=radio id='chk_files' name='chk_files' value='#{index}'>"
-
end
-
ret += "<input type=hidden id='filenames_#{index}' name='filenames[#{index}]' value='"+File.dirname(disp)+"/" +File.basename(path)+"'>"
-
if File.ftype( disp ) == "directory"
-
ret += "<a title='Expand/Collapse' href='#' onclick='javascript:collapseSubDirectory(#{index}); return false;'><img id='expand.#{index}' alt='Expand/Collapse' title='Expand/Collapse' src='/images/up.png'></a> "
-
ret += link_to path, :controller=>'submitted_content', :action => 'edit', :id => participant.id, :download => File.basename(path), "current_folder[name]" => File.dirname(disp)
-
ret += "</li>"
-
ret += list_sub_directories(disp, participant)
-
else
-
ret += link_to path, :controller=>'submitted_content', :action => 'edit', :id => participant.id, :download => File.basename(path), "current_folder[name]" => File.dirname(disp)
-
ret += "</li>"
-
end
-
}
-
ret += "</ul>"
-
end
-
-
# Installing RubyZip
-
# run the command, gem install rubyzip
-
# restart the server
-
1
def self.unzip_file(file_name, unzip_dir, should_delete)
-
#begin
-
Zip::ZipFile::open(file_name) {
-
|zf| zf.each { |e|
-
safename = FileHelper::sanitize_filename(e.name);
-
fpath = File.join(unzip_dir, safename)
-
FileUtils.mkdir_p(File.dirname(fpath))
-
zf.extract(e, fpath) } }
-
-
if should_delete
-
# The zip file is no longer needed, so delete it
-
File.delete(file_name)
-
end
-
#rescue
-
#end
-
end
-
-
end
-
1
module SurveyHelper
-
-
1
def self.get_assigned_surveys(assignment_id)
-
joiners = AssignmentQuestionnaire.find(:all, :conditions => ["assignment_id = ?", assignment_id])
-
assigned_surveys = []
-
for joiner in joiners
-
survey = Questionnaire.find(joiner.questionnaire_id)
-
assigned_surveys << survey if survey.type == 'SurveyQuestionnaire'
-
end
-
assigned_surveys.sort!{|a,b| a.name <=> b.name}
-
end
-
-
1
def self.get_global_surveys
-
global_surveys = Questionnaire.find(:all, :conditions => ["type = ? and private = ?", 'GlobalSurveyQuestionnaire', false])
-
global_surveys.sort!{|a,b| a.name <=> b.name}
-
end
-
-
1
def self.get_all_available_surveys(assignment_id, role_id)
-
surveys = SurveyHelper::get_assigned_surveys(assignment_id)
-
surveys += SurveyHelper::get_global_surveys unless role_id == 2
-
surveys.sort!{|a,b| a.name <=> b.name}
-
end
-
end
-
1
module TeamHelper
-
-
#separates the file into the necessary elements to create a new user
-
#This method is never called. But it is not an elegant way to call 'generate_team_name'
-
#method in this file, another instance of this method is in team.rb.
-
1
def self.upload_teams(file, assignment_id, options,logger)
-
unknown = Array.new
-
while (rline = file.gets)
-
split_line = rline.split(/,(?=(?:[^\"]*\"[^\"]*\")*(?![^\"]*\"))/)
-
if options[:has_column_names] == "true"
-
name = split_line[0]
-
pos = 1
-
else
-
name = generate_team_name()
-
pos = 0
-
end
-
teams = Team.find(:all, :conditions => ["name =? and assignment_id =?",name,assignment_id])
-
currTeam = teams.first
-
if currTeam != nil && options[:handle_dups] == "rename"
-
name = generate_team_name()
-
currTeam = nil
-
end
-
if options[:handle_dups] == "replace" && teams.first != nil
-
for teamsuser in TeamsUser.find(:all, :conditions => ["team_id =?", currTeam.id])
-
teamsuser.destroy
-
end
-
currTeam.destroy
-
currTeam = nil
-
end
-
if teams.length == 0 || currTeam == nil
-
currTeam = Team.new
-
currTeam.name = name
-
currTeam.assignment_id = assignment_id
-
currTeam.save
-
end
-
-
logger.info "#{split_line.length}"
-
logger.info "#{split_line}"
-
while(pos < split_line.length)
-
user = User.find_by_name(split_line[pos].strip)
-
if user && !(options[:handle_dups] == "ignore" && teams.length > 0)
-
teamusers = TeamsUser.find(:all, :conditions => ["team_id =? and user_id =?", currTeam.id,user.id])
-
currUser = teamusers.first
-
if teamusers.length == 0 || currUser == nil
-
currUser = TeamsUser.new
-
currUser.team_id = currTeam.id
-
currUser.user_id = user.id
-
currUser.save
-
-
Participant.create(:assignment_id => assignment_id, :user_id => user.id, :permission_granted => true)
-
end
-
else
-
unknown << split_line[pos]
-
end
-
pos = pos+1
-
end
-
end
-
-
return unknown
-
end
-
-
1
def self.generate_team_name()
-
counter = 0
-
while (true)
-
temp = "Team #{counter}"
-
if (!Team.find_by_name(temp))
-
return temp
-
end
-
counter=counter+1
-
end
-
end
-
-
end
-
1
module TeamsParticipantsHelper
-
end
-
1
module TeamsUsersHelper
-
end
-
1
module TreeDisplayHelper
-
end
-
1
require 'open-uri'
-
#require 'date'
-
1
require 'time'
-
#NOTE: Use time instead of date for speed reasons. See:
-
#http://www.recentrambles.com/pragmatic/view/33
-
-
##
-
# WikiHelper
-
#
-
# author: Jeffrey T. Haug
-
#
-
##
-
1
module WikiHelper
-
-
-
##
-
# review_dokuwiki
-
#
-
# author: Jeffrey T. Haug
-
#
-
# usage: To be used in a view such as:
-
#
-
# <%= review_dokuwiki 'http://pg-server.ece.ncsu.edu/dokuwiki/doku.php/ece633:hw1', '2007/06/11', 'jthaug' %>
-
#
-
# @args: _assignment_url (URL of the wiki assignment.)
-
# @args: _start_date (all review items older will be filtered out)
-
# @args: _wiki_user (wiki user id to crawl)
-
##
-
1
def self.review_dokuwiki(_assignment_url, _start_date = nil, _wiki_user = nil)
-
-
response = '' #the response from the URL
-
-
#Check to make sure we were passed a valid URL
-
matches = /http:/.match( _assignment_url )
-
if not matches
-
return response
-
end
-
-
#Args
-
url = _assignment_url.chomp("/")
-
wiki_url = _assignment_url.scan(/(.*?)doku.php/)
-
namespace = _assignment_url.split(/\//)
-
namespace_url = namespace.last
-
_wiki_user.gsub!(" ","+")
-
-
#Doku Wiki Specific
-
index = "?idx=" + namespace_url
-
review = "?do=revisions" #"?do=recent"
-
-
-
#Grab all relevant urls from index page ####################
-
url += index
-
open(url,
-
"User-Agent" => "Ruby/#{RUBY_VERSION}",
-
"From" => "email@addr.com", #Put pg admin email address here
-
"Referer" => "http://") { |f| #Put pg URL here
-
-
# Save the response body
-
response = f.read
-
-
}
-
-
#Clean URLs
-
response = response.gsub(/href=\"(.*?)doku.php/, 'href="' + wiki_url[0].to_s + 'doku.php')
-
-
#Get all URLs
-
index_urls = response.scan(/href=\"(.*?)\"/)
-
-
namespace_urls = Array.new #Create array to store all URLs in this namespace
-
namespace_urls << _assignment_url
-
-
#Narrow down to all URLs in our namespace
-
index_urls.each_with_index do |index_url, index|
-
-
scan_result = index_url[0].scan(_assignment_url + ":") #scan current item
-
-
if _assignment_url + ":" === scan_result[0]
-
namespace_urls << index_urls[index].to_s
-
end
-
-
end
-
-
#Create a array for all of our review_items
-
review_items = Array.new
-
-
#Process Each page in our namespace
-
namespace_urls.each_with_index do |cur_url, index|
-
-
#return cur_url + review
-
url = namespace_urls[index].to_s
-
url += review
-
#return url
-
open(url,
-
"User-Agent" => "Ruby/#{RUBY_VERSION}",
-
"From" => "email@addr.com", #Put pg admin email address here
-
"Referer" => "http://") { |f| #Put pg URL here
-
-
# Save the response body
-
response = f.read
-
-
}
-
-
## DOKUWIKI PARSING
-
-
#Clean URLs
-
response = response.gsub(/href=\"(.*?)doku.php/,'href="' + wiki_url[0].to_s + 'doku.php')
-
-
# Luckily, dokuwiki uses a structure like:
-
# <!-- wikipage start -->
-
# Content
-
# <!-- wikipage stop -->
-
#
-
#Get everything between the words "wikipage"
-
changes = response.split(/wikipage/)
-
#Trim the "start -->" from "<!-- wikipage start -->"
-
changes = changes[1].sub(/start -->/,"")
-
#Trim the "<!--" from "<!-- wikipage stop -->"
-
response = changes.sub(/<!--/,"")
-
-
-
#Extract each line item
-
line_items = response.scan(/<li>(.*?)<\/li>/)
-
-
#Extract the dates only
-
dates = response.scan(/\d\d\d\d\/\d\d\/\d\d \d\d\:\d\d/)
-
-
-
#if wiki username provided we only want their line items
-
if _wiki_user
-
-
#Remove line items that do not contain this user
-
line_items.each_with_index do |item, index|
-
scan_result = item[0].scan(_wiki_user) #scan current item
-
-
if not _wiki_user === scan_result[0] #no match for wiki user --> eliminate
-
line_items[index] = nil
-
dates[index] = nil
-
end
-
-
end
-
-
line_items.compact!
-
dates.compact!
-
end
-
-
#if start date provided we only want date line items since start date
-
if _start_date
-
-
-
#NOTE: The date_lines index = dates index
-
-
#Convert _start_date
-
start_date = Time.parse(_start_date)
-
-
#Remove dates before deadline
-
dates.each_with_index do |date, index|
-
-
#The date is before start of review
-
if Time.parse(date) < start_date
-
line_items.delete_at(index)
-
end
-
-
end
-
-
end
-
-
-
review_items = review_items + line_items
-
-
end
-
-
return review_items
-
-
-
end
-
-
-
##
-
# review_mediawiki
-
#
-
# author: Jeffrey T. Haug
-
#
-
# usage: To be used in a view such as:
-
#
-
# <%= review_mediawiki 'http://pg-server.ece.ncsu.edu/mediawiki/index.php/ECE633:hw1', '2007/06/11', 'jthaug' %>
-
#
-
# @args: _assignment_url (URL of the wiki assignment.)
-
# @args: _start_date (all review items older will be filtered out)
-
# @args: _wiki_user (wiki user id to crawl)
-
##
-
1
def self.review_mediawiki(_assignment_url, _start_date = nil, _wiki_user = nil)
-
-
response = '' #the response from the URL
-
-
#Check to make sure we were passed a valid URL
-
matches = /http:/.match( _assignment_url )
-
if not matches
-
return response
-
end
-
-
#Args
-
url = _assignment_url.chomp("/")
-
wiki_url = _assignment_url.scan(/(.*?)index.php/)
-
namespace = _assignment_url.split(/\//)
-
namespace_url = namespace.last
-
_wiki_user.gsub!(" ","+")
-
-
#Media Wiki Specific
-
review = "index.php?title=Special:Contributions&target=" + _wiki_user+"&offset=0&limit=1000"
-
-
#Grab this user's contributions
-
-
url = wiki_url[0].to_s + review
-
@urlin = url
-
open(url,
-
"User-Agent" => "Ruby/#{RUBY_VERSION}",
-
"From" => "email@addr.com", #Put pg admin email address here
-
"Referer" => "http://") { |f| #Put pg URL here
-
-
# Save the response body
-
response = f.read
-
@resp = response
-
}
-
-
#Clean URLs
-
response = response.gsub(/href=\"(.*?)index.php/,'href="' + wiki_url[0].to_s + 'index.php')
-
@res = response
-
#Mediawiki uses a structure like:
-
# <!-- start content -->
-
# Content
-
# <!-- end content -->
-
#
-
#Get everything between the words "wikipage"
-
changes = response.split(/<!-- start content -->/)
-
changes2 = changes[1].split(/<!-- end content -->/)
-
response = changes2[0]
-
-
#Extract each line item
-
line_items = response.scan(/<li>.*<\/li>/)
-
-
#Extract the dates only
-
dates = response.scan(/\d\d:\d\d, \d+ \w+ \d\d\d\d/)
-
-
#if start date provided we only want date line items since start date
-
if _start_date
-
-
-
#NOTE: The date_lines index = dates index
-
-
#Convert _start_date
-
start_date = Time.parse(_start_date)
-
-
#Remove dates before deadline
-
dates.each_with_index do |date, index|
-
-
#The date is before start of review
-
if Time.parse(date) < start_date
-
line_items.delete_at(index)
-
end
-
-
end
-
-
end
-
-
-
#Remove line items that not in this namespace
-
line_items.each_with_index do |item, index|
-
-
scan_result = item.scan(namespace_url)
-
-
if not namespace_url === scan_result[0]
-
line_items[index] = nil
-
end
-
-
end
-
-
line_items.compact!
-
-
# Only keep the most recently updated instance of each page
-
pages = Array.new
-
line_items_kept = Array.new
-
-
line_items.each{|item|
-
urls = item.split("<a href=\"")
-
#select the line containing the URL for the page
-
pageArray = urls[3].split("\"")
-
# select the URL itself from the line of text
-
# if it exists within the pages list, we don't need it
-
# otherwise include it in the kept lines
-
if !pages.index(pageArray[0])
-
line_items_kept << item
-
pages << pageArray[0]
-
end
-
}
-
line_items = line_items_kept
-
-
formatted_line_items =Array.new
-
formatted_line_items << "<ul>"
-
formatted_line_items << line_items
-
formatted_line_items << "</ul>"
-
return formatted_line_items
-
-
end
-
end
-
1
class DelayedMailer
-
#Keeps info required for delayed job
-
#to send mail at a particular time
-
1
attr_accessor :assignment_id
-
1
attr_accessor :deadline_type
-
1
attr_accessor :due_at
-
-
1
def initialize(assignment_id, deadline_type, due_at)
-
self.assignment_id=assignment_id
-
self.deadline_type=deadline_type
-
self.due_at = due_at
-
end
-
-
1
def perform
-
assignment = Assignment.find(self.assignment_id)
-
if assignment != nil && assignment.id != nil
-
if(self.deadline_type == "metareview")
-
mail_metareviewers
-
if (assignment.team_assignment?)
-
teamMails = getTeamMembersMail
-
email_reminder(teamMails, "teammate review")
-
end
-
end
-
-
if(self.deadline_type == "review")
-
mail_reviewers # to all reviewers
-
end
-
-
if(self.deadline_type == "submission"|| self.deadline_type == "resubmission")
-
mail_signed_up_users # to all signed up users
-
end
-
-
if(self.deadline_type == "drop_topic")
-
sign_up_topics = SignUpTopic.find(:all, :conditions => ['assignment_id = ?', self.assignment_id])
-
if(sign_up_topics != nil && sign_up_topics.count != 0)
-
mail_signed_up_users #reminder to signed_up users of the assignment
-
end
-
end
-
-
if(self.deadline_type == "signup")
-
sign_up_topics = SignUpTopic.find(:all, :conditions => ['assignment_id = ?', self.assignment_id])
-
if(sign_up_topics != nil && sign_up_topics.count != 0)
-
mail_assignment_participants #reminder to all participants
-
end
-
end
-
-
if(self.deadline_type == "team_formation")
-
assignment = Assignment.find(self.assignment_id)
-
if(assignment.team_assignment?)
-
mail_assignment_participants
-
else
-
emails = Array.new
-
email_reminder(emails, self.deadline_type)
-
end
-
end
-
end
-
end
-
-
# Find the signed_up_users of the assignment and send mails to them
-
1
def mail_signed_up_users
-
emails = Array.new
-
assignment = Assignment.find(self.assignment_id)
-
sign_up_topics = SignUpTopic.find(:all, :conditions => ['assignment_id = ?', self.assignment_id])
-
-
# If there are sign_up topics for an assignement then send a mail toonly signed_up_users else send a mail to all participants
-
if(sign_up_topics == nil || sign_up_topics.count == 0)
-
unless assignment.team_assignment?
-
mail_assignment_participants
-
else
-
teamMails = getTeamMembersMail
-
for mail in teamMails
-
emails << mail
-
email_reminder(emails, self.deadline_type)
-
end
-
end
-
else
-
for topic in sign_up_topics
-
signedUpUsers = SignedUpUser.find(:all, :conditions => ['topic_id = ?', topic.id])
-
unless assignment.team_assignment?
-
for signedUser in signedUpUsers
-
uid = signedUser.creator_id
-
user = User.find(uid)
-
emails << user.email
-
end
-
else
-
for signedUser in signedUpUsers
-
teamid = signedUser.creator_id
-
team_members = TeamsUser.find_all_by_team_id(teamid)
-
for team_member in team_members
-
user = User.find(team_member.user_id)
-
emails << user.email
-
end
-
end
-
end
-
end
-
email_reminder(emails, self.deadline_type)
-
end
-
end
-
-
1
def getTeamMembersMail
-
teamMembersMailList = Array.new
-
assignment = Assignment.find(self.assignment_id)
-
teams = Team.find(:all, :conditions => ['parent_id = ?', self.assignment_id])
-
for team in teams
-
team_participants = TeamsUser.find(:all, :conditions => ['team_id = ?', team.id])
-
for team_participant in team_participants
-
user = User.find(team_participant.user_id)
-
teamMembersMailList << user.email
-
end
-
end
-
return teamMembersMailList
-
end
-
-
1
def mail_metareviewers
-
emails = Array.new
-
#find reviewers for the assignment
-
reviewer_tuples = ResponseMap.find(:all, :conditions => ['reviewed_object_id = ? AND (type = "ParticipantReviewResponseMap" OR type = "TeamReviewResponseMap")', self.assignment_id])
-
for reviewer in reviewer_tuples
-
#find metareviewers - people who will review the reviewers
-
meta_reviewer_tuples = ResponseMap.find(:all, :conditions => ['reviewed_object_id = ? AND type = "MetareviewResponseMap"', reviewer.id])
-
for metareviewer in meta_reviewer_tuples
-
participant = Participant.find(:first, :conditions => ['parent_id = ? AND id = ?', self.assignment_id, metareviewer.reviewer_id])
-
uid = participant.user_id
-
user = User.find(uid)
-
emails << user.email
-
end
-
end
-
email_reminder(emails, self.deadline_type)
-
end
-
-
1
def mail_reviewers
-
emails = Array.new
-
reviewer_tuples = ResponseMap.find(:all, :conditions => ['reviewed_object_id = ? AND (type = "ParticipantReviewResponseMap" OR type = "TeamReviewResponseMap")', self.assignment_id])
-
for reviewer in reviewer_tuples
-
participant = Participant.find(:first, :conditions => ['parent_id = ? AND id = ?', self.assignment_id, reviewer.reviewer_id])
-
uid = participant.user_id
-
user = User.find(uid)
-
emails << user.email
-
end
-
email_reminder(emails, self.deadline_type)
-
end
-
-
1
def mail_assignment_participants
-
emails = Array.new
-
assignment = Assignment.find(self.assignment_id)
-
for participant in assignment.participants
-
uid=participant.user_id
-
user=User.find(uid)
-
emails << user.email
-
end
-
email_reminder(emails, self.deadline_type)
-
end
-
-
1
def email_reminder(emails, deadlineType)
-
assignment = Assignment.find(self.assignment_id)
-
subject = "Message regarding #{deadlineType} for assignment #{assignment.name}"
-
body = "This is a reminder to complete #{deadlineType} for assignment #{assignment.name}. Deadline is #{self.due_at}.If you have already done the #{deadlineType}, Please ignore this mail."
-
-
if (deadlineType == "resubmission")
-
body += "Author feedback is optional. However, if you want to give author feedback then the deadline is #{self.due_at}."
-
end
-
-
Mailer.deliver_message(
-
{:bcc => emails,
-
:subject => subject,
-
:body => body
-
})
-
end
-
end
-
-
# Administrator Class
-
# Subtype of User class
-
# Author: unknown
-
1
class Administrator < User
-
-
1
QUESTIONNAIRE = [["My instructors' questionnaires",'list_instructors'],
-
['My questionnaires','list_mine'],
-
['All public questionnaires','list_all']]
-
-
1
SIGNUPSHEET = [["My instructors' signups",'list_instructors'],
-
['My signups','list_mine'],
-
['All public signups','list_all']]
-
-
1
ASSIGNMENT = [["My instructors' assignments",'list_instructors'],
-
['My assignments','list_mine'],
-
['All public assignments','list_all']]
-
-
1
def list_instructors(object_type, user_id)
-
object_type.find(:all,
-
:joins => "inner join users on " + object_type.to_s.pluralize + ".instructor_id = users.id AND users.parent_id = " + user_id.to_s)
-
end
-
-
1
def list_all(object_type, user_id)
-
object_type.find(:all,
-
:conditions => ["instructor_id = ? OR private = 0", user_id])
-
end
-
-
# This method gets a questionnaire or an assignment, making sure that current user is allowed to see it.
-
1
def get(object_type, id, user_id)
-
object_type.find(:first,
-
:conditions => ["id = ? AND (instructor_id = ? OR private = 0)",
-
id, user_id]) # You are allowed to get it if it is public, or if your id is the one that created it.
-
end
-
end
-
1
module QuestionAnalytic
-
1
def unique_character_count
-
self.txt.gsub(/[^0-9A-Za-z ]/, '').downcase.split(" ").uniq.count
-
end
-
-
1
def character_count
-
self.txt.bytesize
-
end
-
-
1
def word_count
-
self.txt.gsub(/[^0-9A-Za-z]/, ' ').split(' ').count
-
end
-
end
-
1
require 'analytic/question_analytic'
-
1
module QuestionnaireAnalytic
-
#return all possible questionnaire types
-
1
def self.types
-
type_list = Array.new
-
self.all.each do |questionnaire|
-
if !type_list.include?(questionnaire.type)
-
type_list << questionnaire.type
-
end
-
end
-
type_list
-
end
-
-
1
def num_questions
-
self.questions.count
-
end
-
-
1
def questions_text_list
-
question_list = Array.new
-
self.questions.each do |questions|
-
question_list << question.txt
-
end
-
question_list
-
end
-
-
1
def word_count_list
-
word_count_list = Array.new
-
self.questions.each do |question|
-
word_count_list << question.word_count_list
-
end
-
end
-
-
1
def total_word_count
-
word_count_list.inject(:+)
-
end
-
-
1
def average_word_count
-
total_word_count.to_f/num_questions
-
end
-
-
1
def character_count_list
-
character_count_list = Array.new
-
self.questions.each do |question|
-
character_count_list << question.character_count
-
end
-
end
-
-
1
def total_character_count
-
character_count_list.inject(:+)
-
end
-
-
1
def average_character_count
-
total_character_count/num_questions
-
end
-
-
end
-
1
module ScoreAnalytic
-
1
def unique_character_count
-
self.comments.gsub(/[^0-9A-Za-z ]/, '').downcase.split(" ").uniq.count
-
end
-
-
1
def character_count
-
self.comments.bytesize
-
end
-
-
1
def word_count
-
self.comments.gsub(/[^0-9A-Za-z]/, ' ').split(' ').count
-
end
-
end
-
1
class Assignment < ActiveRecord::Base
-
1
require 'analytic/assignment_analytic'
-
1
include AssignmentAnalytic
-
1
include DynamicReviewMapping
-
-
#alias_attribute :team_count, :max_team_size
-
-
# Does not necessarily belong to a course!
-
1
belongs_to :course
-
1
belongs_to :wiki_type
-
# wiki_type needs to be removed. When an assignment is created, it needs to
-
# be created as an instance of a subclass of the Assignment (model) class;
-
# then Rails will "automatically' set the type field to the value that
-
# designates an assignment of the appropriate type.
-
1
has_many :participants, :class_name => 'AssignmentParticipant', :foreign_key => 'parent_id'
-
1
has_many :participant_review_mappings, :class_name => 'ParticipantReviewResponseMap', :through => :participants, :source => :review_mappings
-
1
has_many :users, :through => :participants
-
1
has_many :due_dates
-
1
has_many :teams, :class_name => 'AssignmentTeam', :foreign_key => 'parent_id'
-
1
has_many :team_review_mappings, :class_name => 'TeamReviewResponseMap', :through => :teams, :source => :review_mappings
-
1
has_many :invitations, :class_name => 'Invitation', :foreign_key => 'assignment_id'
-
1
has_many :assignment_questionnaires
-
1
has_many :questionnaires, :through => :assignment_questionnaires
-
1
belongs_to :instructor, :class_name => 'User', :foreign_key => 'instructor_id'
-
1
has_many :sign_up_topics, :foreign_key => 'assignment_id', :dependent => :destroy
-
1
has_many :response_maps, :foreign_key => 'reviewed_object_id', :class_name => 'ResponseMap'
-
#TODO: A bug in Rails http://dev.rubyonrails.org/ticket/4996 prevents us from using this:
-
# has_many :responses, :through => :response_maps, :source => 'response'
-
-
1
validates_presence_of :name
-
1
validates_uniqueness_of :name
-
#validates_presence_of :directory_path, :on => :update
-
#validates_uniqueness_of :scope => [:directory_path, :instructor_id]
-
-
1
COMPLETE = 'Finished'
-
1
WAITLIST = 'Waitlist open'
-
-
1
REVIEW_QUESTIONNAIRES = {:author_feedback => 0, :metareview => 1, :review => 2, :teammate_review => 3}
-
-
1
REVIEW_QUESTIONNAIRES = {:author_feedback => 0, :metareview => 1, :review => 2, :teammate_review => 3}
-
-
# Review Strategy information.
-
1
RS_INSTRUCTOR_SELECTED = 'Instructor-Selected'
-
1
RS_STUDENT_SELECTED = 'Student-Selected'
-
1
RS_AUTO_SELECTED = 'Auto-Selected'
-
1
REVIEW_STRATEGIES = [RS_INSTRUCTOR_SELECTED, RS_STUDENT_SELECTED, RS_AUTO_SELECTED]
-
-
1
DEFAULT_MAX_REVIEWERS = 3
-
-
1
def team_assignment?
-
max_team_size > 1
-
end
-
-
1
def team_assignment
-
team_assignment?
-
end
-
-
# Returns a set of topics that can be reviewed.
-
# We choose the topics if one of its submissions has received the fewest reviews so far
-
1
def candidate_topics_to_review
-
return nil if sign_up_topics.empty? # This is not a topic assignment
-
-
contributor_set = Array.new(contributors)
-
-
# Reject contributors that have not selected a topic, or have no submissions
-
contributor_set.reject! { |contributor| signed_up_topic(contributor).nil? or !contributor.has_submissions? }
-
-
# Reject contributions of topics whose deadline has passed
-
contributor_set.reject! { |contributor| contributor.assignment.get_current_stage(signed_up_topic(contributor).id) == 'Complete' or
-
contributor.assignment.get_current_stage(signed_up_topic(contributor).id) == 'submission' }
-
-
# Filter the contributors with the least number of reviews
-
# (using the fact that each contributor is associated with a topic)
-
contributor = contributor_set.min_by { |contributor| contributor.review_mappings.count }
-
-
min_reviews = contributor.review_mappings.count rescue 0
-
contributor_set.reject! { |contributor| contributor.review_mappings.count > min_reviews + review_topic_threshold }
-
-
candidate_topics = Set.new
-
contributor_set.each { |contributor| candidate_topics.add(signed_up_topic(contributor)) }
-
candidate_topics
-
end
-
-
1
def has_topics?
-
@has_topics ||= !sign_up_topics.empty?
-
end
-
-
1
def has_teams?
-
@has_teams ||= !self.teams.empty?
-
end
-
-
1
def assign_reviewer_dynamically(reviewer, topic)
-
# The following method raises an exception if not successful which
-
# has to be captured by the caller (in review_mapping_controller)
-
contributor = contributor_to_review(reviewer, topic)
-
-
contributor.assign_reviewer(reviewer)
-
end
-
-
# Returns a contributor to review if available, otherwise will raise an error
-
1
def contributor_to_review(reviewer, topic)
-
raise 'Please select a topic' if has_topics? and topic.nil?
-
raise 'This assignment does not have topics' if !has_topics? and topic
-
-
# This condition might happen if the reviewer waited too much time in the
-
# select topic page and other students have already selected this topic.
-
# Another scenario is someone that deliberately modifies the view.
-
if topic
-
raise 'This topic has too many reviews; please select another one.' unless candidate_topics_to_review.include?(topic)
-
end
-
-
p "contributors.nil?"
-
p contributors.nil?
-
p "Contributors:"
-
p contributors.class
-
p contributors.size
-
contributor_set = Array.new(contributors)
-
work = (topic.nil?) ? 'assignment' : 'topic'
-
-
# 1) Only consider contributors that worked on this topic; 2) remove reviewer as contributor
-
# 3) remove contributors that have not submitted work yet
-
contributor_set.reject! do |contributor|
-
signed_up_topic(contributor) != topic or # both will be nil for assignments with no signup sheet
-
contributor.includes?(reviewer) or
-
!contributor.has_submissions?
-
end
-
raise "There are no more submissions to review on this #{work}." if contributor_set.empty?
-
-
# Reviewer can review each contributor only once
-
contributor_set.reject! { |contributor| contributor.reviewed_by?(reviewer) }
-
raise "You have already reviewed all submissions for this #{work}." if contributor_set.empty?
-
-
# Reduce to the contributors with the least number of reviews ("responses") received
-
min_contributor = contributor_set.min_by { |a| a.responses.count }
-
min_reviews = min_contributor.responses.count
-
contributor_set.reject! { |contributor| contributor.responses.count > min_reviews }
-
-
# Pick the contributor whose most recent reviewer was assigned longest ago
-
if min_reviews > 0
-
# Sort by last review mapping id, since it reflects the order in which reviews were assigned
-
# This has a round-robin effect
-
# Sorting on id assumes that ids are assigned sequentially in the db.
-
# .last assumes the database returns rows in the order they were created.
-
# Added unit tests to ensure these conditions are both true with the current database.
-
contributor_set.sort! { |a, b| a.review_mappings.last.id <=> b.review_mappings.last.id }
-
end
-
-
# Choose a contributor at random (.sample) from the remaining contributors.
-
# Actually, we SHOULD pick the contributor who was least recently picked. But sample
-
# is much simpler, and probably almost as good, given that even if the contributors are
-
# picked in round-robin fashion, the reviews will not be submitted in the same order that
-
# they were picked.
-
contributor_set.sample
-
end
-
-
1
def contributors
-
p "in contributors method:"
-
p "teams.size"
-
p teams.size
-
#ACS Contributors are just teams, so removed check to see if it is a team assignment
-
@contributors ||= teams #ACS
-
end
-
-
1
def assign_metareviewer_dynamically(metareviewer)
-
# The following method raises an exception if not successful which
-
# has to be captured by the caller (in review_mapping_controller)
-
response_map = response_map_to_metareview(metareviewer)
-
-
response_map.assign_metareviewer(metareviewer)
-
end
-
-
# Returns a review (response) to metareview if available, otherwise will raise an error
-
1
def response_map_to_metareview(metareviewer)
-
response_map_set = Array.new(review_mappings)
-
-
# Reject response maps without responses
-
response_map_set.reject! { |response_map| !response_map.response }
-
raise 'There are no reviews to metareview at this time for this assignment.' if response_map_set.empty?
-
-
# Reject reviews where the metareviewer was the reviewer or the contributor
-
response_map_set.reject! do |response_map|
-
(response_map.reviewee == metareviewer) or (response_map.reviewer.includes?(metareviewer))
-
end
-
raise 'There are no more reviews to metareview for this assignment.' if response_map_set.empty?
-
-
# Metareviewer can only metareview each review once
-
response_map_set.reject! { |response_map| response_map.metareviewed_by?(metareviewer) }
-
raise 'You have already metareviewed all reviews for this assignment.' if response_map_set.empty?
-
-
# Reduce to the response maps with the least number of metareviews received
-
response_map_set.sort! { |a, b| a.metareview_response_maps.count <=> b.metareview_response_maps.count }
-
min_metareviews = response_map_set.first.metareview_response_maps.count
-
response_map_set.reject! { |response_map| response_map.metareview_response_maps.count > min_metareviews }
-
-
# Reduce the response maps to the reviewers with the least number of metareviews received
-
reviewers = Hash.new # <reviewer, number of metareviews>
-
response_map_set.each do |response_map|
-
reviewer = response_map.reviewer
-
reviewers.member?(reviewer) ? reviewers[reviewer] += 1 : reviewers[reviewer] = 1
-
end
-
reviewers = reviewers.sort { |a, b| a[1] <=> b[1] }
-
min_metareviews = reviewers.first[1]
-
reviewers.reject! { |reviewer| reviewer[1] == min_metareviews }
-
response_map_set.reject! { |response_map| reviewers.member?(response_map.reviewer) }
-
-
# Pick the response map whose most recent metareviewer was assigned longest ago
-
response_map_set.sort! { |a, b| a.metareview_response_maps.count <=> b.metareview_response_maps.count }
-
min_metareviews = response_map_set.first.metareview_response_maps.count
-
if min_metareviews > 0
-
# Sort by last metareview mapping id, since it reflects the order in which reviews were assigned
-
# This has a round-robin effect
-
response_map_set.sort! { |a, b| a.metareview_response_maps.last.id <=> b.metareview_response_maps.last.id }
-
end
-
-
# The first review_map is the best candidate to metareview
-
response_map_set.first
-
end
-
-
1
def is_using_dynamic_reviewer_assignment?
-
if self.review_assignment_strategy == RS_AUTO_SELECTED or
-
self.review_assignment_strategy == RS_STUDENT_SELECTED
-
true
-
else
-
false
-
end
-
end
-
-
1
def review_mappings
-
#ACS Removed the if condition(and corressponding else) which differentiate assignments as team and individual assignments
-
# to treat all assignments as team assignments
-
TeamReviewResponseMap.find_all_by_reviewed_object_id(self.id)
-
end
-
-
1
def metareview_mappings
-
mappings = Array.new
-
self.review_mappings.each do |map|
-
mmap = MetareviewResponseMap.find_by_reviewed_object_id(map.id)
-
if mmap != nil
-
mappings << mmap
-
end
-
end
-
mappings
-
end
-
-
1
def get_scores(questions)
-
scores = Hash.new
-
-
scores[:participants] = Hash.new
-
self.participants.each do |participant|
-
scores[:participants][participant.id.to_s.to_sym] = participant.get_scores(questions)
-
end
-
#ACS Removed the if condition(and corressponding else) which differentiate assignments as team and individual assignments
-
# to treat all assignments as team assignments
-
scores[:teams] = Hash.new
-
index = 0
-
self.teams.each do |team|
-
scores[:teams][index.to_s.to_sym] = Hash.new
-
scores[:teams][index.to_s.to_sym][:team] = team
-
assessments = TeamReviewResponseMap.get_assessments_for(team)
-
scores[:teams][index.to_s.to_sym][:scores] = Score.compute_scores(assessments, questions[:review])
-
#... = ScoreCache.get_participant_score(team, id, questionnaire.display_type)
-
index += 1
-
end
-
scores
-
end
-
-
1
def get_contributor(contrib_id)
-
if team_assignment?
-
return AssignmentTeam.find(contrib_id)
-
else
-
return AssignmentParticipant.find(contrib_id)
-
end
-
end
-
-
# parameterized by questionnaire
-
1
def get_max_score_possible(questionnaire)
-
max = 0
-
sum_of_weights = 0
-
num_questions = 0
-
questionnaire.questions.each { |question| #type identifies the type of questionnaire
-
sum_of_weights += question.weight
-
num_questions+=1
-
}
-
max = num_questions * questionnaire.max_question_score * sum_of_weights
-
return max, sum_of_weights
-
end
-
-
1
def get_path
-
if self.course_id == nil and self.instructor_id == nil
-
raise 'Path cannot be created. The assignment must be associated with either a course or an instructor.'
-
end
-
if self.wiki_type_id != 1
-
raise PathError, 'No path needed'
-
end
-
if self.course_id != nil && self.course_id > 0
-
path = Course.find(self.course_id).get_path
-
else
-
path = RAILS_ROOT + '/pg_data/' + FileHelper.clean_path(User.find(self.instructor_id).name) + '/'
-
end
-
return path + FileHelper.clean_path(self.directory_path)
-
end
-
-
# Check whether review, metareview, etc.. is allowed
-
# If topic_id is set, check for that topic only. Otherwise, check to see if there is any topic which can be reviewed(etc) now
-
1
def check_condition(column, topic_id=nil)
-
# the drop topic deadline should not play any role in picking the next due date
-
# get the drop_topic_deadline_id to exclude it
-
drop_topic_deadline_id = DeadlineType.find_by_name('drop_topic').id
-
if self.staggered_deadline?
-
# next_due_date - the nearest due date that hasn't passed
-
if topic_id
-
# next for topic
-
next_due_date = TopicDeadline.find(:first, :conditions => ['topic_id = ? and due_at >= ? and deadline_type_id <> ?', topic_id, Time.now, drop_topic_deadline_id], :order => 'due_at')
-
else
-
# next for assignment
-
next_due_date = TopicDeadline.find(:first, :conditions => ['assignment_id = ? and due_at >= ? and deadline_type_id <> ?', self.id, Time.now, drop_topic_deadline_id], :joins => {:topic => :assignment}, :order => 'due_at')
-
end
-
else
-
next_due_date = DueDate.find(:first, :conditions => ['assignment_id = ? and due_at >= ? and deadline_type_id <> ?', self.id, Time.now, drop_topic_deadline_id], :order => 'due_at')
-
end
-
-
if next_due_date.nil?
-
return false
-
end
-
-
# command pattern - get the attribute with the name in column
-
# Here, column is usually something like 'review_allowed_id'
-
-
right_id = next_due_date.send column
-
-
right = DeadlineRight.find(right_id)
-
#puts "DEBUG RIGHT_ID = " + right_id.to_s
-
#puts "DEBUG RIGHT = " + right.name
-
return (right and (right.name == 'OK' or right.name == 'Late'))
-
end
-
-
# Determine if the next due date from now allows for submissions
-
1
def submission_allowed(topic_id=nil)
-
return (check_condition('submission_allowed_id', topic_id) )
-
end
-
-
# Determine if the next due date from now allows for reviews
-
1
def review_allowed(topic_id=nil)
-
return (check_condition('review_allowed_id', topic_id) )
-
end
-
-
# Determine if the next due date from now allows for metareviews
-
1
def metareview_allowed(topic_id=nil)
-
return check_condition('review_of_review_allowed_id', topic_id)
-
end
-
-
1
def delete(force = nil)
-
begin
-
maps = ParticipantReviewResponseMap.find_all_by_reviewed_object_id(self.id)
-
maps.each { |map| map.delete(force) }
-
rescue
-
raise "At least one review response exists for #{self.name}."
-
end
-
-
begin
-
maps = TeamReviewResponseMap.find_all_by_reviewed_object_id(self.id)
-
maps.each { |map| map.delete(force) }
-
rescue
-
raise "At least one review response exists for #{self.name}."
-
end
-
-
begin
-
maps = TeammateReviewResponseMap.find_all_by_reviewed_object_id(self.id)
-
maps.each { |map| map.delete(force) }
-
rescue
-
raise "At least one teammate review response exists for #{self.name}."
-
end
-
-
self.invitations.each { |invite| invite.destroy }
-
self.teams.each { |team| team.delete }
-
self.participants.each { |participant| participant.delete }
-
self.due_dates.each { |date| date.destroy }
-
-
# The size of an empty directory is 2
-
# Delete the directory if it is empty
-
begin
-
directory = Dir.entries(RAILS_ROOT + '/pg_data/' + self.directory_path)
-
rescue
-
# directory is empty
-
end
-
-
if !is_wiki_assignment and !self.directory_path.empty? and !directory.nil?
-
if directory.size == 2
-
Dir.delete(RAILS_ROOT + '/pg_data/' + self.directory_path)
-
else
-
raise 'Assignment directory is not empty'
-
end
-
end
-
-
self.assignment_questionnaires.each { |aq| aq.destroy }
-
-
self.destroy
-
end
-
-
# Generate emails for reviewers when new content is available for review
-
#ajbudlon, sept 07, 2007
-
1
def email(author_id)
-
-
# Get all review mappings for this assignment & author
-
participant = AssignmentParticipant.find(author_id)
-
#ACS Removed the if condition(and corressponding else) which differentiate assignments as team and individual assignments
-
# to treat all assignments as team assignments
-
author = participant.team
-
-
for mapping in author.review_mappings
-
-
# If the reviewer has requested an e-mail deliver a notification
-
# that includes the assignment, and which item has been updated.
-
if mapping.reviewer.user.email_on_submission
-
user = mapping.reviewer.user
-
Mailer.deliver_message(
-
{:recipients => user.email,
-
:subject => "A new submission is available for #{self.name}",
-
:body => {
-
:obj_name => self.name,
-
:type => 'submission',
-
:location => get_review_number(mapping).to_s,
-
:first_name => ApplicationHelper::get_user_first_name(user),
-
:partial_name => 'update'
-
}
-
}
-
)
-
end
-
end
-
end
-
-
# Get all review mappings for this assignment & reviewer
-
# required to give reviewer location of new submission content
-
# link cannot be provided as it might give user ability to access data not
-
# available to them.
-
#ajbudlon, sept 07, 2007
-
1
def get_review_number(mapping)
-
reviewer_mappings = ResponseMap.find_all_by_reviewer_id(mapping.reviewer.id)
-
review_num = 1
-
for rm in reviewer_mappings
-
if rm.reviewee.id != mapping.reviewee.id
-
review_num += 1
-
else
-
break
-
end
-
end
-
return review_num
-
end
-
-
# It appears that this method is not used at present!
-
1
def is_wiki_assignment
-
return (self.wiki_type_id > 1)
-
end
-
-
# Check to see if assignment is a microtask
-
1
def is_microtask?
-
return (self.microtask.nil?) ? False : self.microtask
-
end
-
-
1
def self.is_submission_possible (assignment)
-
# Is it possible to upload a file?
-
# Check whether the directory text box is nil
-
if assignment.directory_path != nil && assignment.wiki_type == 1
-
return true
-
# Is it possible to submit a URL (or a wiki page)
-
elsif assignment.directory_path != nil && /(^$)|(^(http|https):\/\/[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(([0-9]{1,5})?\/.*)?$)/ix.match(assignment.directory_path)
-
# In this case we have to check if the directory_path starts with http / https.
-
return true
-
# Is it possible to submit a Google Doc?
-
# removed because google doc not implemented
-
# elsif assignment.wiki_type == 4 #GOOGLE_DOC
-
# return true
-
else
-
return false
-
end
-
end
-
-
1
def is_google_doc
-
# This is its own method so that it can be refactored later.
-
# Google Document code should never directly check the wiki_type_id
-
# and should instead always call is_google_doc.
-
self.wiki_type_id == 4
-
end
-
-
#add a new participant to this assignment
-
#manual addition
-
# user_name - the user account name of the participant to add
-
1
def add_participant(user_name)
-
user = User.find_by_name(user_name)
-
if user.nil?
-
raise "The user account with the name #{user_name} does not exist. Please <a href='" + url_for(:controller => 'users', :action => 'new') + "'>create</a> the user first."
-
end
-
participant = AssignmentParticipant.find_by_parent_id_and_user_id(self.id, user.id)
-
if participant
-
raise "The user #{user.name} is already a participant."
-
else
-
newpart = AssignmentParticipant.create(:parent_id => self.id, :user_id => user.id, :permission_granted => user.master_permission_granted)
-
newpart.set_handle()
-
end
-
end
-
-
1
def create_node
-
parent = CourseNode.find_by_node_object_id(self.course_id)
-
node = AssignmentNode.create(:node_object_id => self.id)
-
if parent != nil
-
node.parent_id = parent.id
-
end
-
node.save
-
end
-
-
-
1
def get_current_stage(topic_id=nil)
-
if self.staggered_deadline?
-
if topic_id.nil?
-
return 'Unknown'
-
end
-
end
-
due_date = find_current_stage(topic_id)
-
if due_date == nil or due_date == COMPLETE
-
return COMPLETE
-
else
-
return DeadlineType.find(due_date.deadline_type_id).name
-
end
-
end
-
-
-
1
def get_stage_deadline(topic_id=nil)
-
if self.staggered_deadline?
-
if topic_id.nil?
-
return 'Unknown'
-
end
-
end
-
-
due_date = find_current_stage(topic_id)
-
if due_date == nil or due_date == 'Finished'
-
return due_date
-
else
-
return due_date.due_at.to_s
-
end
-
end
-
-
1
def get_review_rounds
-
due_dates = DueDate.find_all_by_assignment_id(self.id)
-
rounds = 0
-
for i in (0 .. due_dates.length-1)
-
deadline_type = DeadlineType.find(due_dates[i].deadline_type_id)
-
if deadline_type.name == 'review'
-
rounds = rounds + 1
-
end
-
end
-
rounds
-
end
-
-
-
1
def find_current_stage(topic_id=nil)
-
if self.staggered_deadline?
-
due_dates = TopicDeadline.find(:all,
-
:conditions => ['topic_id = ?', topic_id],
-
:order => 'due_at DESC')
-
else
-
due_dates = DueDate.find(:all,
-
:conditions => ['assignment_id = ?', self.id],
-
:order => 'due_at DESC')
-
end
-
if due_dates != nil and due_dates.size > 0
-
if Time.now > due_dates[0].due_at
-
return 'Finished'
-
else
-
i = 0
-
for due_date in due_dates
-
if Time.now < due_date.due_at and
-
(due_dates[i+1] == nil or Time.now > due_dates[i+1].due_at)
-
return due_date
-
end
-
i = i + 1
-
end
-
end
-
end
-
end
-
-
1
def assign_reviewers(mapping_strategy)
-
#ACS Always assign reviewers for a team
-
#removed check to see if it is a team assignment
-
#defined in DynamicReviewMapping module
-
assign_reviewers_for_team(mapping_strategy)
-
end
-
-
#this is for staggered deadline assignments or assignments with signup sheet
-
1
def assign_reviewers_staggered(num_reviews, num_review_of_reviews)
-
#defined in DynamicReviewMapping module
-
message = assign_reviewers_automatically(num_reviews, num_review_of_reviews)
-
return message
-
end
-
-
1
def get_current_due_date()
-
due_date = self.find_current_stage()
-
if due_date == nil or due_date == 'Finished'
-
return 'Finished'
-
else
-
return due_date
-
end
-
end
-
-
-
# Returns hash review_scores[reviewer_id][reviewee_id] = score
-
1
def compute_reviews_hash
-
review_questionnaire_id = get_review_questionnaire_id()
-
@questions = Question.find(:all, :conditions => ['questionnaire_id = ?', review_questionnaire_id])
-
@review_scores = Hash.new
-
#ACS Removed the if condition(and corressponding else) which differentiate assignments as team and individual assignments
-
# to treat all assignments as team assignments
-
@response_type = 'TeamReviewResponseMap'
-
-
@myreviewers = ResponseMap.find(:all, :select => 'DISTINCT reviewer_id', :conditions => ['reviewed_object_id = ? and type = ? ', self.id, @type])
-
-
@response_maps=ResponseMap.find(:all, :conditions => ['reviewed_object_id = ? and type = ?', self.id, @response_type])
-
for response_map in @response_maps
-
# Check if response is there
-
@corresponding_response = Response.find(:first, :conditions => ['map_id = ?', response_map.id])
-
@respective_scores = Hash.new
-
if @review_scores[response_map.reviewer_id] != nil
-
@respective_scores = @review_scores[response_map.reviewer_id]
-
end
-
if @corresponding_response != nil
-
@this_review_score_raw = Score.get_total_score(:response => @corresponding_response, :questions => @questions, :q_types => Array.new)
-
if @this_review_score_raw >= 0.0
-
@this_review_score = ((@this_review_score_raw*100).round/100.0)
-
end
-
else
-
@this_review_score = 0.0
-
end
-
@respective_scores[response_map.reviewee_id] = @this_review_score
-
@review_scores[response_map.reviewer_id] = @respective_scores
-
end
-
return @review_scores
-
end
-
-
1
def get_review_questionnaire_id()
-
@revqids = []
-
@revqids = AssignmentQuestionnaire.find(:all, :conditions => ['assignment_id = ?', self.id])
-
@revqids.each do |rqid|
-
rtype = Questionnaire.find(rqid.questionnaire_id).type
-
if rtype == 'ReviewQuestionnaire'
-
@review_questionnaire_id = rqid.questionnaire_id
-
end
-
-
end
-
return @review_questionnaire_id
-
end
-
-
1
def get_next_due_date()
-
due_date = self.find_next_stage()
-
if due_date == nil or due_date == 'Finished'
-
return nil
-
else
-
return due_date
-
end
-
end
-
-
1
def find_next_stage()
-
due_dates = DueDate.find(:all,
-
:conditions => ['assignment_id = ?', self.id],
-
:order => 'due_at DESC')
-
-
if due_dates != nil and due_dates.size > 0
-
if Time.now > due_dates[0].due_at
-
return 'Finished'
-
else
-
i = 0
-
for due_date in due_dates
-
if Time.now < due_date.due_at and
-
(due_dates[i+1] == nil or Time.now > due_dates[i+1].due_at)
-
if i > 0
-
return due_dates[i-1]
-
else
-
return nil
-
end
-
end
-
i = i + 1
-
end
-
-
return nil
-
end
-
end
-
end
-
-
# Returns the number of reviewers assigned to a particular assignment
-
1
def get_total_reviews_assigned
-
self.response_maps.size
-
end
-
-
# get_total_reviews_assigned_by_type()
-
# Returns the number of reviewers assigned to a particular assignment by the type of review
-
# Param: type - String (ParticipantReviewResponseMap, etc.)
-
1
def get_total_reviews_assigned_by_type(type)
-
count = 0
-
self.response_maps.each { |x| count = count + 1 if x.type == type }
-
count
-
end
-
-
# Returns the number of reviews completed for a particular assignment
-
1
def get_total_reviews_completed
-
# TODO A bug in Rails http://dev.rubyonrails.org/ticket/4996 prevents us from using the proper syntax :
-
# self.responses.size
-
-
response_count = 0
-
self.response_maps.each do |response_map|
-
response_count = response_count + 1 unless response_map.response.nil?
-
end
-
-
response_count
-
end
-
-
# Returns the number of reviews completed for a particular assignment by type of review
-
# Param: type - String (ParticipantReviewResponseMap, etc.)
-
1
def get_total_reviews_completed_by_type(type)
-
# TODO A bug in Rails http://dev.rubyonrails.org/ticket/4996 prevents us from using the proper syntax :
-
# self.responses.size
-
-
response_count = 0
-
self.response_maps.each do |response_map|
-
response_count = response_count + 1 if !response_map.response.nil? and response_map.type == type
-
end
-
-
response_count
-
end
-
-
# Returns the number of reviews completed for a particular assignment by type of review
-
# Param: type - String (ParticipantReviewResponseMap, etc.)
-
# Param: date - Filter reviews that were not created on this date
-
1
def get_total_reviews_completed_by_type_and_date(type, date)
-
# TODO A bug in Rails http://dev.rubyonrails.org/ticket/4996 prevents us from using the proper syntax :
-
# self.responses.size
-
-
response_count = 0
-
self.response_maps.each do |response_map|
-
if !response_map.response.nil? and response_map.type == type
-
if (response_map.response.created_at.to_datetime.to_date <=> date) == 0 then
-
response_count = response_count + 1
-
end
-
end
-
end
-
-
response_count
-
end
-
-
# Returns the percentage of reviews completed as an integer (0-100)
-
1
def get_percentage_reviews_completed
-
if get_total_reviews_assigned == 0 then
-
0
-
else
-
((get_total_reviews_completed().to_f / get_total_reviews_assigned.to_f) * 100).to_i
-
end
-
end
-
-
# Returns the average of all responses for this assignment as an integer (0-100)
-
1
def get_average_score
-
return 0 if get_total_reviews_assigned == 0
-
-
sum_of_scores = 0
-
-
self.response_maps.each do |response_map|
-
if !response_map.response.nil? then
-
sum_of_scores = sum_of_scores + response_map.response.get_average_score
-
end
-
end
-
-
(sum_of_scores / get_total_reviews_completed).to_i
-
end
-
-
1
def get_score_distribution
-
distribution = Array.new(101, 0)
-
-
self.response_maps.each do |response_map|
-
if !response_map.response.nil? then
-
score = response_map.response.get_average_score.to_i
-
distribution[score] += 1 if score >= 0 and score <= 100
-
end
-
end
-
-
distribution
-
end
-
-
# Compute total score for this assignment by summing the scores given on all questionnaires.
-
# Only scores passed in are included in this sum.
-
1
def compute_total_score(scores)
-
total = 0
-
self.questionnaires.each do |questionnaire|
-
total += questionnaire.get_weighted_score(self, scores)
-
end
-
return total
-
end
-
-
# Checks whether there are duplicate assignments of the same name by the same instructor.
-
# If the assignments are assigned to courses, it's OK to have duplicate names in different
-
# courses.
-
#
-
# changelog: 5/24/2013
-
# Author: hliu11
-
# old method only works after the assignment is created
-
# cover corner case where assignment have not yet been created
-
1
def duplicate_name?
-
assignments = Assignment.find_all_by_name(self.name)
-
assignments.select { |x| x.instructor_id == self.instructor_id } unless self.instructor_id.nil?
-
assignments.select { |x| x.course_id == self.course_id } unless self.course_id.nil?
-
-
if self.id.nil?
-
#if the assignment have not yet been created i.e: Assignment.new without save
-
assignments.count > 0
-
else
-
assignments.count > 1
-
end
-
end
-
-
1
def signed_up_topic(contributor)
-
# The purpose is to return the topic that the contributor has signed up to do for this assignment.
-
# Returns a record from the sign_up_topic table that gives the topic_id for which the contributor has signed up
-
# Look for the topic_id where the creator_id equals the contributor id (contributor is a team or a participant)
-
if !Team.find_by_name_and_id(contributor.name, contributor.id).nil?
-
contributors_topic = SignedUpUser.find_by_creator_id(contributor.id)
-
else
-
contributors_topic = SignedUpUser.find_by_creator_id(contributor.user_id)
-
end
-
if !contributors_topic.nil?
-
contributors_signup_topic = SignUpTopic.find_by_id(contributors_topic.topic_id)
-
#returns the topic
-
return contributors_signup_topic
-
end
-
end
-
-
1
def self.export(csv, parent_id, options)
-
@assignment = Assignment.find(parent_id)
-
@questions = Hash.new
-
questionnaires = @assignment.questionnaires
-
questionnaires.each {
-
|questionnaire|
-
@questions[questionnaire.symbol] = questionnaire.questions
-
}
-
@scores = @assignment.get_scores(@questions)
-
-
if @scores[:teams].nil?
-
return csv
-
end
-
-
for index in 0 .. @scores[:teams].length - 1
-
team = @scores[:teams][index.to_s.to_sym]
-
for participant in team[:team].get_participants
-
pscore = @scores[:participants][participant.id.to_s.to_sym]
-
tcsv = Array.new
-
tcsv << 'team'+index.to_s
-
-
if options['team_score'] == 'true'
-
if team[:scores]
-
tcsv.push(team[:scores][:max], team[:scores][:avg], team[:scores][:min], participant.fullname)
-
else
-
tcsv.push('---', '---', '---')
-
end
-
end
-
-
if options['submitted_score']
-
if pscore[:review]
-
tcsv.push(pscore[:review][:scores][:max], pscore[:review][:scores][:min], pscore[:review][:scores][:avg])
-
else
-
tcsv.push('---', '---', '---')
-
end
-
end
-
-
if options['metareview_score']
-
if pscore[:metareview]
-
tcsv.push(pscore[:metareview][:scores][:max], pscore[:metareview][:scores][:min], pscore[:metareview][:scores][:avg])
-
else
-
tcsv.push('---', '---', '---')
-
end
-
end
-
-
if options['author_feedback_score']
-
if pscore[:feedback]
-
tcsv.push(pscore[:feedback][:scores][:max], pscore[:feedback][:scores][:min], pscore[:feedback][:scores][:avg])
-
else
-
tcsv.push('---', '---', '---')
-
end
-
end
-
-
if options['teammate_review_score']
-
if pscore[:teammate]
-
tcsv.push(pscore[:teammate][:scores][:max], pscore[:teammate][:scores][:min], pscore[:teammate][:scores][:avg])
-
else
-
tcsv.push('---', '---', '---')
-
end
-
end
-
-
tcsv.push(pscore[:total_score])
-
csv << tcsv
-
end
-
end
-
end
-
-
1
def self.get_export_fields(options)
-
fields = Array.new
-
fields << 'Team Name'
-
-
if options['team_score'] == 'true'
-
fields.push('Team Max', 'Team Avg', 'Team Min')
-
end
-
-
if options['submitted_score']
-
fields.push('Submitted Max', 'Submitted Avg', 'Submitted Min')
-
end
-
-
if options['metareview_score']
-
fields.push('Metareview Max', 'Metareview Avg', 'Metareview Min')
-
end
-
-
if options['author_feedback_score']
-
fields.push('Author Feedback Max', 'Author Feedback Avg', 'Author Feedback Min')
-
end
-
-
if options['teammate_review_score']
-
fields.push('Teammate Review Max', 'Teammate Review Avg', 'Teammate Review Min')
-
end
-
-
fields.push('Final Score')
-
-
return fields
-
end
-
-
1
def find_due_dates(type)
-
self.due_dates.select do |due_date|
-
due_date.deadline_type == DeadlineType.find_by_name(type)
-
end
-
end
-
-
1
def clean_up_due_dates
-
#delete due_dates without due_at
-
self.due_dates.each do |due_date|
-
if due_date.due_at.nil?
-
due_date.delete
-
end
-
end
-
-
submissions = self.find_due_dates('submission') + self.find_due_dates('resubmission')
-
submissions.sort! { |x, y| x.due_at <=> y.due_at }
-
reviews = self.find_due_dates('review') + self.find_due_dates('rereview')
-
reviews.sort! { |x, y| x.due_at <=> y.due_at }
-
-
while submissions.count > self.rounds_of_reviews
-
submissions.last.delete
-
end
-
-
while reviews.count > self.rounds_of_reviews
-
reviews.last.delete
-
end
-
-
if self.require_signup?
-
drop_topic_count = 1
-
else
-
drop_topic_count = 0
-
end
-
-
drop_topic = self.find_due_dates('drop_topic')
-
drop_topic.sort! { |x, y| y.due_at <=> x.due_at }
-
while drop_topic.count > self.drop_topic_count
-
drop_topic.last.delete
-
end
-
end
-
-
#this should be moved to SignUpSheet model after we refactor the SignUpSheet.
-
# returns whether ANY topic has a partner ad; used for deciding whether to show the Advertisements column
-
1
def has_partner_ads?(id)
-
Team.find_by_sql("select * from teams where parent_id = "+id+" AND advertise_for_partner='1'").size > 0
-
end
-
end
-
#Node type for Assignments
-
-
#Author: ajbudlon
-
#Date: 7/18/2008
-
-
1
class AssignmentNode < Node
-
1
belongs_to :assignment, :class_name => "Assignment", :foreign_key => "node_object_id"
-
1
belongs_to :node_object, :class_name => 'Assignment'
-
# Returns the table in which to locate Assignments
-
1
def self.table
-
"assignments"
-
end
-
-
# parameters:
-
# sortvar: valid strings - name, created_at, updated_at, directory_path
-
# sortorder: valid strings - asc, desc
-
# user_id: instructor id for assignment
-
# parent_id: course_id if subset
-
-
# returns: list of AssignmentNodes based on query
-
1
def self.get(sortvar = nil,sortorder =nil,user_id = nil,show = nil,parent_id = nil)
-
65
if show
-
65
if User.find(user_id).role.name != "Teaching Assistant"
-
65
conditions = 'assignments.instructor_id = ?'
-
else
-
conditions = 'assignments.course_id in (?)'
-
end
-
else
-
if User.find(user_id).role.name != "Teaching Assistant"
-
conditions = '(assignments.private = 0 or assignments.instructor_id = ?)'
-
else
-
conditions = '(assignments.private = 0 or assignments.course_id in (?))'
-
end
-
end
-
-
65
if User.find(user_id).role.name != "Teaching Assistant"
-
65
values = user_id
-
else
-
values = Ta.get_mapped_courses(user_id)
-
end
-
-
65
if parent_id
-
conditions += " and course_id = #{parent_id}"
-
end
-
-
65
if sortvar.nil?
-
sortvar = 'name'
-
end
-
65
if sortorder.nil?
-
sortorder = 'ASC'
-
end
-
-
65
find(:all, :include => :assignment, :conditions => [conditions,values], :order => "assignments.#{sortvar} #{sortorder}")
-
end
-
-
# Indicates that this object is always a leaf
-
1
def is_leaf
-
true
-
end
-
-
# Gets the name from the associated object
-
1
def get_name
-
Assignment.find(self.node_object_id).name
-
end
-
-
# Gets the directory_path from the associated object
-
1
def get_directory
-
Assignment.find(self.node_object_id).directory_path
-
end
-
-
# Gets the created_at from the associated object
-
1
def get_creation_date
-
Assignment.find(self.node_object_id).created_at
-
end
-
-
# Gets the updated_at from the associated object
-
1
def get_modified_date
-
Assignment.find(self.node_object_id).updated_at
-
end
-
-
# Gets any TeamNodes associated with this object
-
1
def get_teams
-
TeamNode.get(self.node_object_id)
-
end
-
end
-
1
require 'uri'
-
1
require 'yaml'
-
-
# Code Review: Notice that Participant overloads two different concepts:
-
# contribution and participant (see fields of the participant table).
-
# Consider creating a new table called contributions.
-
1
class AssignmentParticipant < Participant
-
1
require 'wiki_helper'
-
-
1
belongs_to :assignment, :class_name => 'Assignment', :foreign_key => 'parent_id'
-
1
has_many :review_mappings, :class_name => 'ParticipantReviewResponseMap', :foreign_key => 'reviewee_id'
-
1
has_many :responses, :finder_sql => 'SELECT r.* FROM responses r, response_maps m, participants p WHERE r.map_id = m.id AND m.type = \'ParticipantReviewResponseMap\' AND m.reviewee_id = p.id AND p.id = #{id}'
-
1
belongs_to :user
-
-
1
validates_presence_of :handle
-
-
1
def includes?(participant)
-
return participant == self
-
end
-
-
1
def assign_reviewer(reviewer)
-
ParticipantReviewResponseMap.create(:reviewee_id => self.id, :reviewer_id => reviewer.id,
-
:reviewed_object_id => assignment.id)
-
end
-
-
# Evaluates whether this participant contribution was reviewed by reviewer
-
# @param[in] reviewer AssignmentParticipant object
-
1
def reviewed_by?(reviewer)
-
return ParticipantReviewResponseMap.count(:conditions => ['reviewee_id = ? AND reviewer_id = ? AND reviewed_object_id = ?',
-
self.id, reviewer.id, assignment.id]) > 0
-
end
-
-
1
def has_submissions?
-
return ((get_submitted_files.length > 0) or
-
(get_wiki_submissions.length > 0) or
-
(get_hyperlinks_array.length > 0))
-
end
-
-
# all the participants in this assignment reviewed by this person
-
1
def get_reviewees
-
reviewees = []
-
if self.assignment.team_assignment?
-
rmaps = ResponseMap.find(:all, :conditions => ["reviewer_id = #{self.id} AND type = 'TeamReviewResponseMap'"])
-
rmaps.each do |rm|
-
reviewees.concat(AssignmentTeam.find(rm.reviewee_id).participants)
-
end
-
else
-
rmaps = ResponseMap.find(:all, :conditions => ["reviewer_id = #{self.id} AND type = 'ParticipantReviewResponseMap'"])
-
rmaps.each do |rm|
-
reviewees.push(AssignmentParticipant.find(rm.reviewee_id))
-
end
-
end
-
return reviewees
-
end
-
-
# all the participants in this assignment who have reviewed this person
-
1
def get_reviewers
-
reviewers = []
-
if self.assignment.team_assignment? && self.team
-
rmaps = ResponseMap.find(:all, :conditions => ["reviewee_id = #{self.team.id} AND type = 'TeamReviewResponseMap'"])
-
else
-
rmaps = ResponseMap.find(:all, :conditions => ["reviewee_id = #{self.id} AND type = 'ParticipantReviewResponseMap'"])
-
end
-
rmaps.each do |rm|
-
reviewers.push(AssignmentParticipant.find(rm.reviewer_id))
-
end
-
return reviewers
-
end
-
-
# Cycle data structure
-
# Each edge of the cycle stores a participant and the score given by to the participant by the reviewer.
-
# Consider a 3 node cycle: A --> B --> C --> A (A reviewed B; B reviewed C and C reviewed A)
-
# For the above cycle, the data structure would be: [[A, SCA], [B, SAB], [C, SCB]], where SCA is the score given by C to A.
-
-
1
def get_two_node_cycles
-
cycles = []
-
self.get_reviewers.each do |ap|
-
if ap.get_reviewers.include?(self)
-
self.get_reviews_by_reviewer(ap).nil? ? next : s01 = self.get_reviews_by_reviewer(ap).get_total_score
-
ap.get_reviews_by_reviewer(self).nil? ? next : s10 = ap.get_reviews_by_reviewer(self).get_total_score
-
cycles.push([[self, s01], [ap, s10]])
-
end
-
end
-
return cycles
-
end
-
-
1
def get_three_node_cycles
-
cycles = []
-
self.get_reviewers.each do |ap1|
-
ap1.get_reviewers.each do |ap2|
-
if ap2.get_reviewers.include?(self)
-
self.get_reviews_by_reviewer(ap1).nil? ? next : s01 = self.get_reviews_by_reviewer(ap1).get_total_score
-
ap1.get_reviews_by_reviewer(ap2).nil? ? next : s12 = ap1.get_reviews_by_reviewer(ap2).get_total_score
-
ap2.get_reviews_by_reviewer(self).nil? ? next : s20 = ap2.get_reviews_by_reviewer(self).get_total_score
-
cycles.push([[self, s01], [ap1, s12], [ap2, s20]])
-
end
-
end
-
end
-
return cycles
-
end
-
-
1
def get_four_node_cycles
-
cycles = []
-
self.get_reviewers.each do |ap1|
-
ap1.get_reviewers.each do |ap2|
-
ap2.get_reviewers.each do |ap3|
-
if ap3.get_reviewers.include?(self)
-
self.get_reviews_by_reviewer(ap1).nil? ? next : s01 = self.get_reviews_by_reviewer(ap1).get_total_score
-
ap1.get_reviews_by_reviewer(ap2).nil? ? next : s12 = ap1.get_reviews_by_reviewer(ap2).get_total_score
-
ap2.get_reviews_by_reviewer(ap3).nil? ? next : s23 = ap2.get_reviews_by_reviewer(ap3).get_total_score
-
ap3.get_reviews_by_reviewer(self).nil? ? next : s30 = ap3.get_reviews_by_reviewer(self).get_total_score
-
cycles.push([[self, s01], [ap1, s12], [ap2, s23], [ap3, s30]])
-
end
-
end
-
end
-
end
-
return cycles
-
end
-
-
# Per cycle
-
1
def get_cycle_similarity_score(cycle)
-
similarity_score = 0.0
-
count = 0.0
-
for pivot in 0 ... cycle.size-1 do
-
pivot_score = cycle[pivot][1]
-
# puts "Pivot:" + cycle[pivot][1].to_s
-
for other in pivot+1 ... cycle.size do
-
# puts "Other:" + cycle[other][1].to_s
-
similarity_score = similarity_score + (pivot_score - cycle[other][1]).abs
-
count = count + 1.0
-
end
-
end
-
similarity_score = similarity_score / count unless count == 0.0
-
return similarity_score
-
end
-
-
# Per cycle
-
1
def get_cycle_deviation_score(cycle)
-
deviation_score = 0.0
-
count = 0.0
-
for member in 0 ... cycle.size do
-
participant = AssignmentParticipant.find(cycle[member][0].id)
-
total_score = participant.get_review_score
-
deviation_score = deviation_score + (total_score - cycle[member][1]).abs
-
count = count + 1.0
-
end
-
deviation_score = deviation_score / count unless count == 0.0
-
return deviation_score
-
end
-
-
1
def get_review_score
-
review_questionnaire = self.assignment.questionnaires.select {|q| q.type == "ReviewQuestionnaire"}[0]
-
assessment = review_questionnaire.get_assessments_for(self)
-
return (Score.compute_scores(assessment, review_questionnaire.questions)[:avg] / 100.00) * review_questionnaire.max_possible_score.to_f
-
end
-
-
1
def fullname
-
self.user.fullname
-
end
-
-
1
def name
-
self.user.name
-
end
-
-
# Return scores that this participant has been given
-
1
def get_scores(questions)
-
scores = Hash.new
-
scores[:participant] = self # This doesn't appear to be used anywhere
-
self.assignment.questionnaires.each do |questionnaire|
-
scores[questionnaire.symbol] = Hash.new
-
scores[questionnaire.symbol][:assessments] = questionnaire.get_assessments_for(self)
-
scores[questionnaire.symbol][:scores] = Score.compute_scores(scores[questionnaire.symbol][:assessments], questions[questionnaire.symbol])
-
end
-
scores[:total_score] = assignment.compute_total_score(scores)
-
-
# In the event that this is a microtask, we need to scale the score accordingly and record the total possible points
-
# PS: I don't like the fact that we are doing this here but it is difficult to make it work anywhere else
-
if assignment.is_microtask?
-
topic = SignUpTopic.find_by_assignment_id(assignment.id)
-
if !topic.nil?
-
scores[:total_score] *= (topic.micropayment.to_f / 100.to_f)
-
scores[:max_pts_available] = topic.micropayment
-
end
-
end
-
-
return scores
-
end
-
-
# Appends the hyperlink to a list that is stored in YAML format in the DB
-
# @exception If is hyperlink was already there
-
# If it is an invalid URL
-
1
def submmit_hyperlink(hyperlink)
-
hyperlink.strip!
-
raise "The hyperlink cannot be empty" if hyperlink.empty?
-
-
url = URI.parse(hyperlink)
-
-
# If not a valid URL, it will throw an exception
-
Net::HTTP.start(url.host, url.port)
-
-
hyperlinks = get_hyperlinks_array
-
-
hyperlinks << hyperlink
-
self.submitted_hyperlinks = YAML::dump(hyperlinks)
-
-
self.save
-
end
-
-
# Note: This method is not used yet. It is here in the case it will be needed.
-
# @exception If the index does not exist in the array
-
1
def remove_hyperlink(index)
-
hyperlinks = get_hyperlinks
-
raise "The link does not exist" unless index < hyperlinks.size
-
-
hyperlinks.delete_at(index)
-
self.submitted_hyperlinks = hyperlinks.empty? ? nil : YAML::dump(hyperlinks)
-
-
self.save
-
end
-
-
1
def get_members
-
team.try :participants
-
end
-
-
-
1
def get_hyperlinks
-
team.try :get_hyperlinks
-
end
-
-
1
def get_hyperlinks_array
-
self.submitted_hyperlinks.nil? ? [] : YAML::load(self.submitted_hyperlinks)
-
end
-
-
#Copy this participant to a course
-
1
def copy(course_id)
-
part = CourseParticipant.find_by_user_id_and_parent_id(self.user_id,course_id)
-
if part.nil?
-
CourseParticipant.create(:user_id => self.user_id, :parent_id => course_id)
-
end
-
end
-
-
1
def get_course_string
-
# if no course is associated with this assignment, or if there is a course with an empty title, or a course with a title that has no printing characters ...
-
begin
-
course = Course.find(self.assignment.course.id)
-
if course.name.strip.length == 0
-
raise
-
end
-
return course.name
-
rescue
-
return "<center>—</center>"
-
end
-
end
-
-
1
def get_feedback
-
return FeedbackResponseMap.get_assessments_for(self)
-
end
-
-
1
def get_reviews
-
#ACS Always get assessments for a team
-
#removed check to see if it is a team assignment
-
return TeamReviewResponseMap.get_assessments_for(self.team)
-
end
-
-
1
def get_reviews_by_reviewer(reviewer)
-
if self.assignment.team_assignment?
-
return TeamReviewResponseMap.get_reviewer_assessments_for(self.team, reviewer)
-
else
-
return ParticipantReviewResponseMap.get_reviewer_assessments_for(self, reviewer)
-
end
-
end
-
-
1
def get_reviews_by_reviewer(reviewer)
-
if self.assignment.team_assignment?
-
return TeamReviewResponseMap.get_reviewer_assessments_for(self.team, reviewer)
-
else
-
return ParticipantReviewResponseMap.get_reviewer_assessments_for(self, reviewer)
-
end
-
end
-
-
1
def get_metareviews
-
MetareviewResponseMap.get_assessments_for(self)
-
end
-
-
1
def get_teammate_reviews
-
TeammateReviewResponseMap.get_assessments_for(self)
-
end
-
-
1
def get_submitted_files()
-
files = Array.new
-
if(self.directory_num)
-
files = get_files(self.get_path)
-
end
-
return files
-
end
-
-
1
def get_files(directory)
-
files_list = Dir[directory + "/*"]
-
files = Array.new
-
for file in files_list
-
if File.directory?(file) then
-
dir_files = get_files(file)
-
dir_files.each{|f| files << f}
-
end
-
files << file
-
end
-
return files
-
end
-
-
1
def get_wiki_submissions
-
currenttime = Time.now.month.to_s + "/" + Time.now.day.to_s + "/" + Time.now.year.to_s
-
-
#ACS Check if the team count is greater than one(team assignment)
-
if self.assignment.max_team_size > 1 and self.assignment.wiki_type.name == "MediaWiki"
-
submissions = Array.new
-
if self.team
-
self.team.get_participants.each {
-
| user |
-
val = WikiType.review_mediawiki_group(self.assignment.directory_path, currenttime, user.handle)
-
if val != nil
-
submissions << val
-
end
-
}
-
end
-
return submissions
-
elsif self.assignment.wiki_type.name == "MediaWiki"
-
return WikiType.review_mediawiki(self.assignment.directory_path, currenttime, self.handle)
-
elsif self.assignment.wiki_type.name == "DocuWiki"
-
return WikiType.review_docuwiki(self.assignment.directory_path, currenttime, self.handle)
-
else
-
return Array.new
-
end
-
end
-
-
1
def name
-
self.user.name
-
end
-
-
1
def team
-
AssignmentTeam.get_team(self)
-
end
-
-
# provide import functionality for Assignment Participants
-
# if user does not exist, it will be created and added to this assignment
-
1
def self.import(row,session,id)
-
if row.length < 1
-
raise ArgumentError, "No user id has been specified."
-
end
-
user = User.find_by_name(row[0])
-
if (user == nil)
-
if row.length < 4
-
raise ArgumentError, "The record containing #{row[0]} does not have enough items."
-
end
-
attributes = ImportFileHelper::define_attributes(row)
-
user = ImportFileHelper::create_new_user(attributes,session)
-
end
-
if Assignment.find(id) == nil
-
raise ImportError, "The assignment with id \""+id.to_s+"\" was not found."
-
end
-
if (find(:all, {:conditions => ['user_id=? AND parent_id=?', user.id, id]}).size == 0)
-
newpart = AssignmentParticipant.create(:user_id => user.id, :parent_id => id)
-
newpart.set_handle()
-
end
-
end
-
-
# provide export functionality for Assignment Participants
-
1
def self.export(csv,parent_id,options)
-
find_all_by_parent_id(parent_id).each{
-
|part|
-
user = part.user
-
csv << [
-
user.name,
-
user.fullname,
-
user.email,
-
user.role.name,
-
user.parent.name,
-
user.email_on_submission,
-
user.email_on_review,
-
user.email_on_review_of_review,
-
part.handle
-
]
-
}
-
end
-
-
1
def self.get_export_fields(options)
-
fields = ["name","full name","email","role","parent","email on submission","email on review","email on metareview","handle"]
-
return fields
-
end
-
-
# generate a hash string that we can digitally sign, consisting of the
-
# assignment name, user name, and time stamp passed in.
-
1
def get_hash(time_stamp)
-
# first generate a hash from the assignment name itself
-
hash_data = Digest::SHA1.digest(self.assignment.name.to_s)
-
-
# second generate a hash from the first hash plus the user name and time stamp
-
sign = hash_data + self.user.name.to_s + time_stamp.strftime("%Y-%m-%d %H:%M:%S")
-
Digest::SHA1.digest(sign)
-
end
-
-
# grant publishing rights to one or more assignments. Using the supplied private key,
-
# digital signatures are generated.
-
# reference: http://stuff-things.net/2008/02/05/encrypting-lots-of-sensitive-data-with-ruby-on-rails/
-
1
def self.grant_publishing_rights(privateKey, participants)
-
for participant in participants
-
#now, check to make sure the digital signature is valid, if not raise error
-
participant.permission_granted = participant.verify_digital_signature(privateKey)
-
participant.save
-
raise 'Invalid key' unless participant.permission_granted
-
end
-
end
-
-
# verify the digital signature is valid
-
1
def verify_digital_signature(private_key)
-
user.public_key == OpenSSL::PKey::RSA.new(private_key).public_key.to_pem
-
end
-
-
#define a handle for a new participant
-
1
def set_handle()
-
if self.user.handle == nil or self.user.handle == ""
-
self.handle = self.user.name
-
else
-
if AssignmentParticipant.find_all_by_parent_id_and_handle(self.assignment.id, self.user.handle).length > 0
-
self.handle = self.user.name
-
else
-
self.handle = self.user.handle
-
end
-
end
-
self.save!
-
end
-
-
1
def get_path
-
path = self.assignment.get_path + "/"+ self.directory_num.to_s
-
return path
-
end
-
-
1
def update_resubmit_times
-
new_submit = ResubmissionTime.new(:resubmitted_at => Time.now.to_s)
-
self.resubmission_times << new_submit
-
end
-
-
1
def set_student_directory_num
-
if self.directory_num.nil? or self.directory_num < 0
-
maxnum = AssignmentParticipant.find(:first, :conditions=>['parent_id = ?',self.parent_id], :order => 'directory_num desc').directory_num
-
if maxnum
-
dirnum = maxnum + 1
-
else
-
dirnum = 0
-
end
-
self.update_attribute('directory_num',dirnum)
-
#ACS Get participants irrespective of the number of participants in the team
-
#removed check to see if it is a team assignment
-
self.team.get_participants.each{
-
| member |
-
if member.directory_num == nil or member.directory_num < 0
-
member.directory_num = self.directory_num
-
member.save
-
end
-
}
-
end
-
end
-
-
1
private
-
-
# Use submmit_hyperlink(), remove_hyperlink() instead
-
1
def submitted_hyperlinks=(val)
-
write_attribute :submitted_hyperlinks, val
-
end
-
end
-
-
1
def get_topic_string
-
if topic.nil? or topic.topic_name.empty?
-
return "<center>—</center>"
-
end
-
return topic.topic_name
-
end
-
1
class AssignmentQuestionnaire < ActiveRecord::Base
-
1
belongs_to :assignment
-
1
belongs_to :questionnaire
-
-
-
end
-
1
class AssignmentTeam < Team
-
-
1
belongs_to :assignment, :class_name => 'Assignment', :foreign_key => 'parent_id'
-
1
has_many :review_mappings, :class_name => 'TeamReviewResponseMap', :foreign_key => 'reviewee_id'
-
1
has_many :responses, :finder_sql => 'SELECT r.* FROM responses r, response_maps m, teams t WHERE r.map_id = m.id AND m.type = \'TeamReviewResponseMap\' AND m.reviewee_id = t.id AND t.id = #{id}'
-
-
# START of contributor methods, shared with AssignmentParticipant
-
-
# Whether this team includes a given participant or not
-
1
def includes?(participant)
-
return participants.include?(participant)
-
end
-
-
1
def assign_reviewer(reviewer)
-
TeamReviewResponseMap.create(:reviewee_id => self.id, :reviewer_id => reviewer.id,
-
:reviewed_object_id => assignment.id)
-
end
-
-
# Evaluates whether any contribution by this team was reviewed by reviewer
-
# @param[in] reviewer AssignmentParticipant object
-
1
def reviewed_by?(reviewer)
-
return TeamReviewResponseMap.count(:conditions => ['reviewee_id = ? AND reviewer_id = ? AND reviewed_object_id = ?',
-
self.id, reviewer.id, assignment.id]) > 0
-
end
-
-
# Topic picked by the team
-
1
def topic
-
team_topic = nil
-
-
participants.each do |participant|
-
team_topic = participant.topic
-
break if team_topic
-
end
-
-
team_topic
-
end
-
-
# Whether the team has submitted work or not
-
1
def has_submissions?
-
participants.each do |participant|
-
return true if participant.has_submissions?
-
end
-
return false
-
end
-
-
1
def reviewed_contributor?(contributor)
-
return TeamReviewResponseMap.find(:all,
-
:conditions => ['reviewee_id = ? AND reviewer_id = ? AND reviewed_object_id = ?',
-
contributor.id, self.id, assignment.id]).empty? == false
-
end
-
-
# END of contributor methods
-
-
1
def participants
-
@participants ||= AssignmentParticipant.find(:all, :conditions => ['parent_id = ? and user_id IN (?)', parent_id, users])
-
end
-
-
1
def delete
-
if read_attribute(:type) == 'AssignmentTeam'
-
signup = SignedUpUser.find_team_participants(parent_id.to_s).select{|p| p.creator_id == self.id}
-
signup.each &:destroy
-
end
-
-
super
-
end
-
-
1
def self.get_first_member(team_id)
-
find(team_id).participants.first
-
end
-
-
1
def get_hyperlinks
-
links = Array.new
-
for team_member in self.get_participants
-
links.concat(team_member.get_hyperlinks_array)
-
end
-
return links
-
end
-
-
1
def get_path
-
self.get_participants.first.get_path
-
end
-
-
1
def get_submitted_files
-
self.get_participants.first.get_submitted_files
-
end
-
-
1
def get_review_map_type
-
return 'TeamReviewResponseMap'
-
end
-
-
1
def self.handle_duplicate(team, name, assgt_id, handle_dups)
-
puts ">>>at beginning of handle_duplicate, name = "+ name
-
puts ">>>at beginning of handle_duplicate, handle_dups = "+ handle_dups
-
if team.nil? #no duplicate
-
return name
-
end
-
if handle_dups == "ignore" #ignore: do not create the new team
-
p '>>>setting name to nil ...'
-
return nil
-
end
-
if handle_dups == "rename" #rename: rename new team
-
return self.generate_team_name(Assignment.find(assgt_id).name)
-
end
-
if handle_dups == "replace" #replace: delete old team
-
team.delete
-
return name
-
else # handle_dups = "insert"
-
return nil
-
end
-
end
-
-
1
def self.import(row,session,assgt_id,options)
-
if (row.length < 2 and options[:has_column_names] == "true") or (row.length < 1 and options[:has_column_names] != "true")
-
raise ArgumentError, "Not enough fields on this line"
-
end
-
-
if Assignment.find(assgt_id) == nil
-
raise ImportError, "The assignment with id \""+assgt_id.to_s+"\" was not found. <a href='/assignment/new'>Create</a> this assignment?"
-
end
-
-
if options[:has_column_names] == "true"
-
name = row[0].to_s.strip
-
team = find(:first, :conditions => ["name =? and parent_id =?", name, assgt_id])
-
team_exists = !team.nil?
-
name = handle_duplicate(team, name, assgt_id, options[:handle_dups])
-
index = 1
-
else
-
name = self.generate_team_name(Assignment.find(assgt_id).name)
-
index = 0
-
end
-
-
# create new team for the team to be inserted
-
# do not create new team if we choose 'ignore' or 'insert' duplicate teams
-
if name
-
team=AssignmentTeam.create_team_and_node(assgt_id)
-
team.name = name
-
team.save
-
end
-
-
# insert team members into team unless team was pre-existing & we ignore duplicate teams
-
if !(team_exists && options[:handle_dups] == "ignore")
-
team.import_team_members(index, row)
-
end
-
end
-
-
1
def email
-
self.get_team_users.first.email
-
end
-
-
1
def get_participant_type
-
"AssignmentParticipant"
-
end
-
-
1
def get_parent_model
-
"Assignment"
-
end
-
-
1
def fullname
-
self.name
-
end
-
-
1
def get_participants
-
users = self.users
-
participants = Array.new
-
users.each{
-
| user |
-
participant = AssignmentParticipant.find_by_user_id_and_parent_id(user.id,self.parent_id)
-
if participant != nil
-
participants << participant
-
end
-
}
-
return participants
-
end
-
-
1
def copy(course_id)
-
new_team = CourseTeam.create_team_and_node(course_id)
-
new_team.name = name
-
new_team.save
-
#new_team = CourseTeam.create({:name => self.name, :parent_id => course_id})
-
copy_members(new_team)
-
end
-
-
1
def add_participant(assignment_id, user)
-
if AssignmentParticipant.find_by_parent_id_and_user_id(assignment_id, user.id) == nil
-
AssignmentParticipant.create(:parent_id => assignment_id, :user_id => user.id, :permission_granted => user.master_permission_granted)
-
end
-
end
-
-
1
def assignment
-
Assignment.find(self.parent_id)
-
end
-
-
# return a hash of scores that the team has received for the questions
-
1
def get_scores(questions)
-
scores = Hash.new
-
scores[:team] = self # This doesn't appear to be used anywhere
-
assignment.questionnaires.each do |questionnaire|
-
scores[questionnaire.symbol] = Hash.new
-
scores[questionnaire.symbol][:assessments] = Response.all(:joins => :map,
-
:conditions => {:response_maps => {:reviewee_id => self.id, :type => 'TeamReviewResponseMap'}})
-
scores[questionnaire.symbol][:scores] = Score.compute_scores(scores[questionnaire.symbol][:assessments], questions[questionnaire.symbol])
-
end
-
scores[:total_score] = assignment.compute_total_score(scores)
-
return scores
-
end
-
-
1
def self.get_team(participant)
-
team = nil
-
teams_users = TeamsUser.find_all_by_user_id(participant.user_id)
-
teams_users.each {
-
| tuser |
-
fteam = Team.find(:first, :conditions => ['parent_id = ? and id = ?',participant.parent_id,tuser.team_id])
-
if fteam
-
team = fteam
-
end
-
}
-
team
-
end
-
-
1
def self.export(csv, parent_id, options)
-
currentAssignment = Assignment.find(parent_id)
-
currentAssignment.teams.each { |team|
-
tcsv = Array.new
-
teamUsers = Array.new
-
tcsv.push(team.name)
-
if (options["team_name"] == "false")
-
teamMembers = TeamsUser.find(:all, :conditions => ['team_id = ?', team.id])
-
teamMembers.each do |user|
-
teamUsers.push(user.name)
-
teamUsers.push(" ")
-
end
-
tcsv.push(teamUsers)
-
end
-
tcsv.push(currentAssignment.name)
-
csv << tcsv
-
}
-
end
-
-
1
def self.get_export_fields(options)
-
fields = Array.new
-
fields.push("Team Name")
-
if (options["team_name"] == "false")
-
fields.push("Team members")
-
end
-
fields.push("Assignment Name")
-
end
-
-
1
def self.create_team_and_node(assignment_id)
-
assignment = Assignment.find(assignment_id)
-
teamname = Team.generate_team_name(assignment.name)
-
team = AssignmentTeam.create(:name=>teamname, :parent_id => assignment_id)
-
TeamNode.create(:parent_id =>assignment_id,:node_object_id=>team.id)
-
team
-
end
-
-
1
require './app/models/analytic/assignment_team_analytic'
-
1
include AssignmentTeamAnalytic
-
end
-
1
class AuthorFeedbackQuestionnaire < Questionnaire
-
1
def after_initialize
-
self.display_type = 'Author Feedback'
-
end
-
-
1
def symbol
-
return "feedback".to_sym
-
end
-
-
1
def get_assessments_for(participant)
-
participant.get_feedback()
-
end
-
-
-
end
-
1
class Authority
-
1
attr_reader :current_user
-
-
1
def initialize(args = {})
-
@current_user = args[:current_user]
-
end
-
-
1
def allow?(controller, action)
-
return true if current_user && current_user.admin?
-
case controller
-
when 'pages'
-
true
-
end
-
end
-
end
-
1
require 'automated_metareview/text_preprocessing'
-
1
require 'automated_metareview/predict_class'
-
1
require 'automated_metareview/degree_of_relevance'
-
1
require 'automated_metareview/plagiarism_check'
-
1
require 'automated_metareview/tone'
-
1
require 'automated_metareview/text_quantity'
-
1
require 'automated_metareview/constants'
-
-
#gem install edavis10-ruby-web-search
-
#gem install google-api-client
-
-
1
class AutomatedMetareview < ActiveRecord::Base
-
#belongs_to :response, :class_name => 'Response', :foreign_key => 'response_id'
-
#has_many :scores, :class_name => 'Score', :foreign_key => 'response_id', :dependent => :destroy
-
1
attr_accessor :responses, :review_array
-
#the code that drives the metareviewing
-
1
def calculate_metareview_metrics(response, map_id)
-
# puts "inside perform_metareviews!!"
-
-
preprocess = TextPreprocessing.new
-
# puts "map_id #{map_id}"
-
#fetch the review data as an array
-
@review_array = preprocess.fetch_review_data(self, map_id)
-
# puts "self.responses #{self.responses}"
-
-
speller = Aspell.new("en_US")
-
speller.suggestion_mode = Aspell::NORMAL
-
@review_array = preprocess.check_correct_spellings(@review_array, speller)
-
# puts "printing review_array"
-
@review_array.each{
-
|rev|
-
puts rev
-
}
-
-
#checking for plagiarism by comparing with question and responses
-
plag_instance = PlagiarismChecker.new
-
result_comparison = plag_instance.compare_reviews_with_questions_responses(self, map_id)
-
# puts "review_array.length #{@review_array.length}"
-
-
if(result_comparison == ALL_RESPONSES_PLAGIARISED)
-
self.content_summative = 0
-
self.content_problem = 0
-
self.content_advisory = 0
-
self.relevance = 0
-
self.quantity = 0
-
self.tone_positive = 0
-
self.tone_negative = 0
-
self.tone_neutral = 0
-
self.plagiarism = true
-
# puts "All responses are copied!!"
-
return
-
elsif(result_comparison == SOME_RESPONSES_PLAGIARISED)
-
self.plagiarism = true
-
end
-
-
#checking plagiarism (by comparing responses with search results from google), we look for quoted text, exact copies i.e.
-
google_plagiarised = plag_instance.google_search_response(self)
-
if(google_plagiarised == true)
-
self.plagiarism = true
-
else
-
self.plagiarism = false
-
end
-
-
# puts "length of review array after google check - #{@review_array.length}"
-
-
if(@review_array.length > 0)
-
#formatting the review responses, segmenting them at punctuations
-
review_text = preprocess.segment_text(0, @review_array)
-
-
#removing quoted text from reviews
-
review_text = preprocess.remove_text_within_quotes(review_text) #review_text is an array
-
-
#fetching submission data as an array and segmenting them at punctuations
-
subm_text = preprocess.segment_text(0, preprocess.fetch_submission_data(map_id))
-
# puts "subm_text #{subm_text}"
-
# #initializing the pos tagger and nlp tagger/semantic parser
-
pos_tagger = EngTagger.new
-
core_NLP_tagger = StanfordCoreNLP.load(:tokenize, :ssplit, :pos, :lemma, :parse, :ner, :dcoref)
-
-
#---------
-
#relevance
-
beginning_time = Time.now
-
relev = DegreeOfRelevance.new
-
self.relevance = relev.get_relevance(review_text, subm_text, 1, pos_tagger, core_NLP_tagger, speller) #1 indicates the number of reviews
-
#assigninging the graph generated for the review to the class variable, in order to reuse it for content classification
-
review_graph = relev.review
-
#calculating end time
-
end_time = Time.now
-
relevance_time = end_time - beginning_time
-
# puts "************* relevance_time - #{relevance_time}"
-
-
#---------
-
# checking for plagiarism
-
if(self.plagiarism != true) #if plagiarism hasn't already been set
-
beginning_time = Time.now
-
result = plag_instance.check_for_plagiarism(review_text, subm_text)
-
if(result == true)
-
self.plagiarism = "TRUE"
-
else
-
self.plagiarism = "FALSE"
-
end
-
end_time = Time.now
-
plagiarism_time = end_time - beginning_time
-
# puts "************* plagiarism_time - #{plagiarism_time}"
-
end
-
#---------
-
#content
-
beginning_time = Time.now
-
content_instance = PredictClass.new
-
pattern_files_array = ["app/models/automated_metareview/patterns-assess.csv",
-
"app/models/automated_metareview/patterns-prob-detect.csv",
-
"app/models/automated_metareview/patterns-suggest.csv"]
-
#predcting class - last parameter is the number of classes
-
content_probs = content_instance.predict_classes(pos_tagger, core_NLP_tagger, review_text, review_graph, pattern_files_array, pattern_files_array.length)
-
#self.content = "SUMMATIVE - #{(content_probs[0] * 10000).round.to_f/10000}, PROBLEM - #{(content_probs[1] * 10000).round.to_f/10000}, SUGGESTION - #{(content_probs[2] * 10000).round.to_f/10000}"
-
end_time = Time.now
-
content_time = end_time - beginning_time
-
self.content_summative = content_probs[0]# * 10000).round.to_f/10000
-
self.content_problem = content_probs[1] #* 10000).round.to_f/10000
-
self.content_advisory = content_probs[2] #* 10000).round.to_f/10000
-
# puts "************* content_time - #{content_time}"
-
#---------
-
# tone
-
beginning_time = Time.now
-
ton = Tone.new
-
tone_array = Array.new
-
tone_array = ton.identify_tone(pos_tagger, core_NLP_tagger, review_text, review_graph)
-
self.tone_positive = tone_array[0]#* 10000).round.to_f/10000
-
self.tone_negative = tone_array[1]#* 10000).round.to_f/10000
-
self.tone_neutral = tone_array[2]#* 10000).round.to_f/10000
-
#self.tone = "POSITIVE - #{(tone_array[0]* 10000).round.to_f/10000}, NEGATIVE - #{(tone_array[1]* 10000).round.to_f/10000}, NEUTRAL - #{(tone_array[2]* 10000).round.to_f/10000}"
-
end_time = Time.now
-
tone_time = end_time - beginning_time
-
# puts "************* tone_time - #{tone_time}"
-
# #---------
-
# quantity
-
beginning_time = Time.now
-
quant = TextQuantity.new
-
self.quantity = quant.number_of_unique_tokens(review_text)
-
end_time = Time.now
-
quantity_time = end_time - beginning_time
-
# puts "************* quantity_time - #{quantity_time}"
-
# #---------
-
# # fetch version_num for this new response_id if previous versions of this response already exists in the table
-
@metas = AutomatedMetareview.find(:first, :conditions => ["response_id = ?", self.response_id], :order => "version_num DESC")
-
if !@metas.nil? and !@metas.version_num.nil?
-
version = @metas.version_num + 1
-
else
-
version = 1 #no metareviews exist with that response_id, so set the version to 1
-
end
-
self.version_num = version
-
end
-
end
-
-
-
=begin
-
The following method 'send_metareview_metrics_email' sends an email to the reviewer
-
listing his/her metareview metrics values.
-
=end
-
1
def send_metareview_metrics_email(response, map_id)
-
response_id = self.response_id
-
reviewer_id = ResponseMap.find_by_id(map_id).reviewer
-
-
reviewer_email = User.find_by_id(Participants.fin_by_id(reviewer_id).user_id).email
-
reviewed_url = @url
-
-
body_text = "The metareview metrics for review #{@url} are as follows: "
-
body_text = body_text + " Relevance: " + self.relevance
-
body_text = body_text + " Quantity: " + self.plagiarism
-
body_text = body_text + " Plagiarised: " + self.quantity
-
body_text = body_text + " Content Type: Summative content " + self.content_summative.to_s +
-
" Problem content "+self.content_problem.to_s + " Advisory content " + self.content_advisory
-
body_text = body_text + " Tone Type: Postive tone " + self.tone_positive.to_s +
-
" Negative tone "+self.tone_negative.to_s + " Neutral tone " + self.tone_neutral
-
-
Mailer.deliver_message(
-
{:recipients => reviewer_email,
-
:subject => "Your metareview metrics for review of Assignment",
-
:from => email_form[:from],
-
:body => {
-
:body_text => body_text
-
}
-
}
-
)
-
-
flash[:notice] = "Your metareview metrics have been emailed."
-
end
-
end
-
1
require 'wordnet'
-
#necessary to access the data.{po} files in the wordnet/dict folder of the rwordnet gem
-
1
include WordNet
-
1
WordNet::SynsetType = {"n" => "noun", "v" => "verb", "a" => "adj", "r" => "adv"}
-
-
-
# Create a parser object
-
#frequently used general constants
-
#prevtype tokens for graph generator
-
1
NOUN = 1
-
1
VERB = 2
-
1
ADJ = 3
-
1
ADV = 4
-
#------------------------------------------#------------------------------------------
-
#constants used by sentence state
-
1
POSITIVE = 0
-
1
SUGGESTIVE = 1
-
1
NEGATED = 2
-
1
NEGATIVE_WORD = 3
-
1
NEGATIVE_DESCRIPTOR = 4
-
1
NEGATIVE_PHRASE = 5
-
#------------------------------------------#------------------------------------------
-
-
#used by patternIdentify and predictClass and relevance, while comparing edges!
-
1
EQUAL = 1.0
-
1
DISTINCT = 2.0
-
#------------------------------------------#------------------------------------------
-
-
#constants used by graph generator
-
1
WORDS = 10000 #to control the number of tokens/vertices a graph contains
-
#thresholds for pruning edges during pattern selection
-
1
ALPHA_FREQ = 2 #alpha - the frequency threshold (lower)
-
1
BETA_FREQ = 10
-
#------------------------------------------#------------------------------------------
-
-
#threshold for tone
-
1
THRESHOLD = 3 #number of level synonyms to check for tone identification
-
#------------------------------------------#------------------------------------------
-
-
#constants used by WordnetBasedSimilarity
-
#initializing constants
-
1
NOMATCH = 0 #distinct
-
1
OVERLAPEXAM = 1 #overlapping examples
-
1
OVERLAPDEFIN = 1 #overlapping definitions
-
1
COMMONPARENTS = 2 #common parents
-
1
MERONYM = 3 #paraphrasing
-
1
HOLONYM = 3 #paraphrasing
-
1
HYPONYM = 4 #paraphrasing
-
1
HYPERNYM = 4 #paraphrasing
-
1
SYNONYM = 5 #paraphrasing
-
1
EXACT = 6 #exact strings
-
-
#negative matches
-
1
NEGOVERLAPEXAM = -1 #overlapping examples
-
1
NEGOVERLAPDEFIN = -1 #overlapping definitions
-
1
NEGCOMMONPARENTS = -2 #common parents
-
1
NEGMERONYM = -3 #paraphrasing
-
1
NEGHOLONYM = -3 #paraphrasing
-
1
NEGHYPONYM = -4 #paraphrasing
-
1
NEGHYPERNYM = -4 #paraphrasing
-
1
ANTONYM = -5 #antonyms
-
1
NEGEXACT = -6 #exact strings
-
#------------------------------------------#------------------------------------------
-
-
#for plgiarism checking - n-gram
-
1
NGRAM = 5 #5-gram matches
-
#other constants for plagiarism checking
-
1
ALL_RESPONSES_PLAGIARISED = 1
-
1
SOME_RESPONSES_PLAGIARISED = 2
-
#------------------------------------------#------------------------------------------
-
-
#constants from text_preprocessing
-
1
SIM_MATCH = 5
-
1
SENTENCES = 100 #assuming each review has upto 5 sentences max.
-
1
MAX = 3000
-
#------------------------------------------#------------------------------------------
-
-
=begin
-
THE FIRST TWO SETS ARE COMMON WORDS DURING OVERLAP ACROSS DEFINITIONS OR EXAMPLES.
-
THE THIRD SET IS TO PREVENT FREQUENT WORDS FROM BEING COMPARED WITH OTHER TOKENS.
-
=end
-
1
CLOSED_CLASS_WORDS = [".", ",", "THE",
-
"AND", "A", "\"", "IN", "I", ":", "YOU", "IS", "TO", "OF",
-
")", "(", "IT", "FOR", "!", "?","THAT","ON", "WITH", "HAVE",
-
"BE", "...", "AS","THIS","WAS", "e.g.", "especially","BUT", "OR", "FROM","WHAT","NOT", "ARE",
-
"MY", "AT", "HE", "BY", "ONE","IF", "THEY", "YOUR","ALL",
-
"ME", "SO", "AN", "WE", "CAN", "WILL", "DO","ABOUT","JUST",
-
"OUT", "HIS", "WHO", "WOULD","THERE","LIKE", "HAS","MORE","UP","NO",
-
"THEM", "ANY", "THEIR", "IT'S", "ONLY", "WHEN","SOME","HAD", "DON'T",
-
";", "I'M", "BEEN", "WHICH", "OTHER", "WERE", "HOW", "THEN", "NOW",
-
"HER", "SHE", "ALSO", "US", "VERY", "BECAUSE","THAN","WELL",
-
"AM", "HIM", "INTO", "OUR", "COULD", "EVEN","MUCH","HERE",
-
"TOO","THESE", "THOSE","MAY", "WHERE", "MOST","SHOULD", "OVER", "WANT", "DID",
-
"WHY", "OFF", "IT", "ITS", "I'VE","MANY","GOING", "THOSE", "DOES","PLEASE",
-
"THAT'S", "YOU'RE", "DOWN","ANOTHER", "AROUND","CAN'T","DIDN'T",
-
"MUST","YES", "EACH", "MAYBE","EVERY", "FEW", "DOESN'T",
-
"I'LL", "OH", "ELSE", "HE'S", "THERE'S", "HI", "AWAY", "DOING","ISN'T",
-
"OK", "THEY'RE", "YEAH", "MINE", "WE'RE", "WHAT'S", "SHALL","WON'T",
-
"SHE'S", "HELLO", "OKAY", "HERE'S", "-", "LESS", "USED", "use", "associated", "having", "certain",
-
"etc", "etc.", "act", "purpose"]
-
-
# @invisible
-
1
STOP_WORDS = ["a", "am", "an", "and", "any", "as", "at", "is", "it", "its","de", "by","i",
-
"ie", "if", "in","no","of", "off", "or", "eg", "the", "too", "are", "the", "he",
-
"about", "above", "across", "after", "afterwards", "again", "against",
-
"all", "almost", "alone", "along", "already", "also", "although", "always",
-
"among", "amongst", "amoungst", "amount", "another",
-
"anyhow", "anyone", "anything", "anyway", "anywhere", "are", "around",
-
"back", "be", "became", "because", "become", "becomes",
-
"becoming", "been", "before", "beforehand", "behind", "being", "below",
-
"beside", "besides", "between", "beyond", "bill", "both", "bottom", "call",
-
"can", "cannot", "cant", "co", "computer", "con", "could",
-
"couldnt", "cry", "describe", "detail", "do", "done", "does", "down",
-
"due", "during", "each", "eight", "either", "eleven", "else", "elsewhere",
-
"empty", "enough", "etc", "even", "ever", "every", "everyone", "everything",
-
"everywhere", "except", "few", "fifteen", "fify", "fill", "find",
-
"fire", "first", "five", "for", "former", "formerly", "forty", "found",
-
"four", "from", "front", "full", "further", "get", "give", "go",
-
"had", "has", "hasnt", "have", "he", "hence", "her", "here", "hereafter",
-
"hereby", "herein", "hereupon", "hers", "herself", "him", "himself", "his",
-
"how", "however", "hundred", "inc", "indeed",
-
"interest", "into", "itself", "keep", "last", "latter",
-
"latterly", "least", "less", "ltd", "made", "many", "may", "me",
-
"meanwhile", "might", "mill", "mine", "more", "moreover", "most", "mostly",
-
"move", "much", "must", "my", "myself", "name", "namely", "neither",
-
"never", "nevertheless", "next", "nine", "nobody", "none", "noone",
-
"nor", "not", "nothing", "now", "nowhere", "often", "on",
-
"once", "one", "only", "onto", "other", "others", "otherwise", "our",
-
"ours", "ourselves", "out", "over", "own", "part", "per", "perhaps",
-
"please", "put", "rather", "re", "same", "see", "seem", "seemed", "seeming",
-
"seems", "serious", "several", "she", "should", "show", "side", "since",
-
"sincere", "six", "sixty", "so", "some", "somehow", "someone", "something",
-
"sometime", "sometimes", "somewhere", "still", "such", "system", "take",
-
"ten", "than", "that", "the", "their", "them", "themselves", "then",
-
"thence", "there", "thereafter", "thereby", "therefore", "therein",
-
"thereupon", "these", "they", "thick", "thin", "third", "this", "those",
-
"though", "three", "through", "throughout", "thru", "thus", "to",
-
"together", "top", "toward", "towards", "twelve", "twenty", "two",
-
"un", "under", "until", "up", "upon", "us", "very", "via", "was", "we",
-
"well", "were", "what", "whatever", "when", "whence", "whenever", "where",
-
"whereafter", "whereas", "whereby", "wherein", "whereupon", "wherever",
-
"whether", "which", "while", "whither", "who", "whoever", "whole", "whom",
-
"whose", "why", "will", "with", "within", "without", "would", "yet",
-
"you", "your", "yours", "yourself", "yourselves", "individual","individually"]
-
-
#tokens containing these words aren't compared with other tokens, because they don't add any meaning
-
1
FREQUENT_WORDS = [ "a", "am", "an", "and", "any", "as",
-
"at", "are","be", "by", "can", "did", "do", "does", "is", "it", "its", "i", "ie", "if", "in","no",
-
"or", "eg", "me", "my","of", "off", "oh", "our", "ours", "was", "have", "has",
-
"so","she", "the", "too", "to","they", "their", "theirs", "that", "this", "then",
-
"there","than", "up", "us", "u", "his", "her", "hers",
-
"we", "with","were", "you", "your", "yours"]
-
-
#puts FREQUENT_WORDS
-
#------------------------------------------#------------------------------------------
-
#constants used by sentence state - for identifying negations and suggestive words
-
-
=begin
-
If negative words were found and a neg. descriptor is seen => (-)(-) = (+)
-
public static String[] NEGATIVE_DESCRIPTORS = new String[4879];
-
=end
-
1
NEGATIVE_DESCRIPTORS = [
-
#negated phrases (topical words I spotted in text)
-
"NOTHING", "nowhere", "scarcely", "scarce", "zero", "drawback",
-
"barely", "hardly", "deny", "refuse", "fail", "failed",
-
"without", "ambiguous", "ambiguity", "neither", "empty",
-
"deviation", "lacks", "lack", "lacking", "lacked", "abrupt", "abruptly", "somewhat", "copied", "copy",
-
"overbalanced", "missing", "poor",
-
"negative", "negatively", "underrepresented", "duplication", "wrong", "mistake", "mistakes","duplications",
-
"duplicate", "duplicated", "duplicating", "avoids", "messy", "deleted", "cumbersome", "strange",
-
"strangely", "misspell", "misspelling", "misspellings", "misspelt", "verbose", "confuse", "confusion", "confusing",
-
"confused", "confuses", "trivial", "triviality", "typo", "typos", "somewhat", "concerns", "concern",
-
"barring", "overuse", "repitition", "useless", "biased", "rushed", "absent", "wordy", "bad", "less",
-
"unclear", "difficult", "vague", "briefly", "hard", "broken","replicate","replicated", "digress", "clutter",
-
"cluttered", "inadequate", "deviation", "contrived", "contrive", "horrid", "trouble","uneven", "unevenly", "alot",
-
"incorrect", "nonsense", "insufficient"]
-
=begin
-
SENTENCE CLAUSE OR PHRASE FOLLOWING THESE WORDS CARRY A NEGATIVE MEANING (EITHER SUBTLE OR OVERT)
-
=end
-
1
NEGATED_WORDS = ["not", "n't", "WON'T", "DON'T", "DIDN'T",
-
"DOESN'T", "WOULDN'T", "COULDN'T", "SHOULDN'T", "WASN'T",
-
"WEREN'T", "AREN'T", "ISN'T", "HAVEN'T", "HASN'T", "HADN'T", "NOBODY",
-
"CAN'T","SHALLN'T", "MUSTN'T", "AIN'T", "cannot",
-
#without the apostrophe
-
"cant", "dont", "wont","isnt","hasnt", "hadnt", "havent","arent", "werent", "wouldnt",
-
"didnt", "couldnt", "shouldnt", "mustnt", "shallnt",
-
#other words that indicate negations (negative quantifiers)
-
"NO", "NEVER", "NONE"]
-
-
1
NEGATIVE_PHRASES = ["too concise",
-
"taken from", "been removed", "too long", "off topic",
-
"too short", "run on", "too much", "been directly", "similar to",
-
"at odds", "grammatical errors", "grammatical error", "available online",
-
"make up", "made up", "crammed up"]
-
-
1
SUGGESTIVE_WORDS = ["would", "could", "should",
-
"maybe", "perhaps", "might", "suggest", "suggests", "suggested", "advise", "advice","could've", "would've",
-
"should've", "might've", "may", #"will", "better", "can"
-
#when they provide sample examples
-
"eg",
-
#typos or colloqial
-
"I'd", "We'd", "they'd", "you'd"]
-
-
#suggestive phrases
-
1
SUGGESTIVE_PHRASES = ["for example","try adding", "instead of", #(explaining what isnt good and what potentially could be)
-
"little more", "try to", "need more", "needs to", "need to", "more detail",
-
"can be", "was expecting", "am expecting", "is required"]
-
-
1
require 'automated_metareview/wordnet_based_similarity'
-
1
require 'automated_metareview/graph_generator'
-
-
1
class DegreeOfRelevance
-
#creating accessors for the instance variables
-
1
attr_accessor :vertex_match
-
1
attr_accessor :review
-
=begin
-
Identifies relevance between a review and a submission
-
=end
-
1
def get_relevance(reviews, submissions, num_reviews, pos_tagger, core_NLP_tagger, speller) #double dimensional arrays that contain the submissions and the reviews respectively
-
review_vertices = nil
-
review_edges = nil
-
subm_vertices = nil
-
subm_edges = nil
-
num_rev_vert = 0
-
num_rev_edg = 0
-
num_sub_vert = 0
-
numSubEdg = 0
-
vert_match = 0.0
-
edge_without_syn = 0.0
-
edge_with_syn = 0.0
-
edge_diff_type = 0.0
-
double_edge = 0.0
-
double_edge_with_syn = 0.0
-
-
#since Reviews and Submissions "should" contain the same number of records review - submission pairs
-
g = GraphGenerator.new
-
#generating review's graph
-
g.generate_graph(reviews, pos_tagger, core_NLP_tagger, true, false)
-
review_vertices = g.vertices
-
review_edges = g.edges
-
num_rev_vert = g.num_vertices
-
num_rev_edg = g.num_edges
-
-
#assigning graph as a review graph to use in content classification
-
@review = g.clone
-
-
#generating the submission's graph
-
g.generate_graph(submissions, pos_tagger, core_NLP_tagger, true, false)
-
subm_vertices = g.vertices
-
subm_edges = g.edges
-
num_sub_vert = g.num_vertices
-
num_sub_edg = g.num_edges
-
-
vert_match = compare_vertices(pos_tagger, review_vertices, subm_vertices, num_rev_vert, num_sub_vert, speller)
-
if(num_rev_edg > 0 and num_sub_edg > 0)
-
edge_without_syn = compare_edges_non_syntax_diff(review_edges, subm_edges, num_rev_edg, num_sub_edg)
-
edge_with_syn = compare_edges_syntax_diff(review_edges, subm_edges, num_rev_edg, num_sub_edg)
-
edge_diff_type = compare_edges_diff_types(review_edges, subm_edges, num_rev_edg, num_sub_edg)
-
edge_match = (edge_without_syn.to_f + edge_with_syn.to_f )/2.to_f #+ edge_diff_type.to_f
-
double_edge = compare_SVO_edges(review_edges, subm_edges, num_rev_edg, num_sub_edg)
-
double_edge_with_syn = compare_SVO_diff_syntax(review_edges, subm_edges, num_rev_edg, num_sub_edg)
-
double_edge_match = (double_edge.to_f + double_edge_with_syn.to_f)/2.to_f
-
else
-
edge_match = 0
-
double_edge_match = 0
-
end
-
-
#differently weighted cases
-
#tweak this!!
-
alpha = 0.55
-
beta = 0.35
-
gamma = 0.1 #alpha > beta > gamma
-
relevance = (alpha.to_f * vert_match.to_f) + (beta * edge_match.to_f) + (gamma * double_edge_match.to_f) #case1's value will be in the range [0-6] (our semantic values)
-
scaled_relevance = relevance.to_f/6.to_f #scaled from [0-6] in the range [0-1]
-
-
#printing values
-
# puts("vertexMatch is [0-6]:: #{vert_match}")
-
# puts("edgeWithoutSyn Match is [0-6]:: #{edge_without_syn}")
-
# puts("edgeWithSyn Match is [0-6]:: #{edge_with_syn}")
-
# puts("edgeDiffType Match is [0-6]:: #{edge_diff_type}")
-
# puts("doubleEdge Match is [0-6]:: #{double_edge}")
-
# puts("doubleEdge with syntax Match is [0-6]:: #{double_edge_with_syn}")
-
# puts("relevance [0-6]:: #{relevance}")
-
# puts("scaled relevance on [0-1]:: #{scaled_relevance}")
-
# puts("*************************************************")
-
return scaled_relevance
-
end
-
=begin
-
* every vertex is compared with every other vertex
-
* Compares the vertices from across the two graphs to identify matches and quantify various metrics
-
* v1- vertices of the submission/past review and v2 - vertices from new review
-
=end
-
1
def compare_vertices(pos_tagger, rev, subm, num_rev_vert, num_sub_vert, speller)
-
# puts("****Inside compare_vertices:: rev.length:: #{num_rev_vert} subm.length:: #{num_sub_vert}")
-
#for double dimensional arrays, one of the dimensions should be initialized
-
@vertex_match = Array.new(num_rev_vert){Array.new}
-
wnet = WordnetBasedSimilarity.new
-
cum_vertex_match = 0.0
-
count = 0
-
max = 0.0
-
flag = 0
-
-
for i in (0..num_rev_vert - 1)
-
if(!rev.nil? and !rev[i].nil?)
-
rev[i].node_id = i
-
# puts("%%%%%%%%%%% Token #{rev[i].name} ::: POS tags:: rev[i].pos_tag:: #{rev[i].pos_tag} :: rev[i].node_id #{rev[i].node_id}")
-
#skipping frequent words from vertex comparison
-
if(wnet.is_frequent_word(rev[i].name))
-
next #ruby equivalent for continue
-
end
-
#looking for the best match
-
#j tracks every element in the set of all vertices, some of which are null
-
for j in (0..num_sub_vert - 1)
-
if(!subm[j].nil?)
-
if(subm[j].node_id == -1)
-
subm[j].node_id = j
-
end
-
# puts("%%%%%%%%%%% Token #{subm[j].name} ::: POS tags:: subm[j].pos_tag:: #{subm[j].pos_tag} subm[j].node_id #{subm[j].node_id}")
-
if(wnet.is_frequent_word(subm[j].name))
-
next #ruby equivalent for continue
-
end
-
#comparing only if one of the two vertices is a noun
-
if(rev[i].pos_tag.include?("NN") and subm[j].pos_tag.include?("NN"))
-
@vertex_match[i][j] = wnet.compare_strings(rev[i], subm[j], speller)
-
#only if the "if" condition is satisfied, since there could be null objects in between and you dont want unnecess. increments
-
flag = 1
-
if(@vertex_match[i][j] > max)
-
max = @vertex_match[i][j]
-
end
-
end
-
end
-
end #end of for loop for the submission vertices
-
-
if(flag != 0)#if the review edge had any submission edges with which it was matched, since not all S-V edges might have corresponding V-O edges to match with
-
# puts("**** Best match for:: #{rev[i].name}-- #{max}")
-
cum_vertex_match = cum_vertex_match + max
-
count+=1
-
max = 0.0 #re-initialize
-
flag = 0
-
end
-
end #end of if condition
-
end #end of for loop
-
-
avg_match = 0.0
-
if(count > 0)
-
avg_match = cum_vertex_match/ count
-
end
-
return avg_match
-
end #end of compare_vertices
-
-
#------------------------------------------#------------------------------------------
-
=begin
-
* SAME TYPE COMPARISON!!
-
* Compares the edges from across the two graphs to identify matches and quantify various metrics
-
* compare SUBJECT-VERB edges with SUBJECT-VERB matches
-
* where SUBJECT-SUBJECT and VERB-VERB or VERB-VERB and OBJECT-OBJECT comparisons are done
-
=end
-
1
def compare_edges_non_syntax_diff(rev, subm, num_rev_edg, num_sub_edg)
-
# puts("*****Inside compareEdgesnNonSyntaxDiff numRevEdg:: #{num_rev_edg} numSubEdg:: #{num_sub_edg}")
-
best_SV_SV_match = Array.new(num_rev_edg){Array.new}
-
cum_edge_match = 0.0
-
count = 0
-
max = 0.0
-
flag = 0
-
-
wnet = WordnetBasedSimilarity.new
-
for i in (0..num_rev_edg - 1)
-
if(!rev[i].nil? and rev[i].in_vertex.node_id != -1 and rev[i].out_vertex.node_id != -1)
-
#skipping edges with frequent words for vertices
-
if(wnet.is_frequent_word(rev[i].in_vertex.name) and wnet.is_frequent_word(rev[i].out_vertex.name))
-
next
-
end
-
-
#looking for best matches
-
for j in (0..num_sub_edg - 1)
-
#comparing in-vertex with out-vertex to make sure they are of the same type
-
if(!subm[j].nil? && subm[j].in_vertex.node_id != -1 && subm[j].out_vertex.node_id != -1)
-
-
#checking if the subm token is a frequent word
-
if(wnet.is_frequent_word(subm[j].in_vertex.name) and wnet.is_frequent_word(subm[j].out_vertex.name))
-
next
-
end
-
-
#carrying out the normal comparison
-
if(rev[i].in_vertex.type == subm[j].in_vertex.type && rev[i].out_vertex.type == subm[j].out_vertex.type)
-
if(!rev[i].label.nil?)
-
if(!subm[j].label.nil?)
-
#taking each match separately because one or more of the terms may be a frequent word, for which no @vertex_match exists!
-
sum = 0.0
-
cou = 0
-
if(!@vertex_match[rev[i].in_vertex.node_id][subm[j].in_vertex.node_id].nil?)
-
sum = sum + @vertex_match[rev[i].in_vertex.node_id][subm[j].in_vertex.node_id]
-
cou +=1
-
end
-
if(!@vertex_match[rev[i].out_vertex.node_id][subm[j].out_vertex.node_id].nil?)
-
sum = sum + @vertex_match[rev[i].out_vertex.node_id][subm[j].out_vertex.node_id]
-
cou +=1
-
end
-
#--Only vertex matches
-
if(cou > 0)
-
best_SV_SV_match[i][j] = sum.to_f/cou.to_f
-
else
-
best_SV_SV_match[i][j] = 0.0
-
end
-
#--Vertex and SRL - Dividing it by the label's match value
-
best_SV_SV_match[i][j] = best_SV_SV_match[i][j]/ compare_labels(rev[i], subm[j])
-
flag = 1
-
if(best_SV_SV_match[i][j] > max)
-
max = best_SV_SV_match[i][j]
-
end
-
end
-
end
-
end
-
end
-
end #end of for loop for the submission edges
-
-
#cumulating the review edges' matches in order to get its average value
-
if(flag != 0) #if the review edge had any submission edges with which it was matched, since not all S-V edges might have corresponding V-O edges to match with
-
# puts("**** Best match for:: #{rev[i].in_vertex.name} - #{rev[i].out_vertex.name} -- #{max}")
-
cum_edge_match = cum_edge_match + max
-
count+=1
-
max = 0.0#re-initialize
-
flag = 0
-
end
-
end
-
end #end of 'for' loop for the review's edges
-
-
#getting the average for all the review edges' matches with the submission's edges
-
avg_match = 0.0
-
if(count > 0)
-
avg_match = cum_edge_match/ count
-
end
-
return avg_match
-
end
-
#------------------------------------------#------------------------------------------
-
=begin
-
* SAME TYPE COMPARISON!!
-
* Compares the edges from across the two graphs to identify matches and quantify various metrics
-
* compare SUBJECT-VERB edges with VERB-OBJECT matches and vice-versa
-
* where SUBJECT-OBJECT and VERB_VERB comparisons are done - same type comparisons!!
-
=end
-
-
1
def compare_edges_syntax_diff(rev, subm, num_rev_edg, num_sub_edg)
-
# puts("*****Inside compareEdgesSyntaxDiff :: numRevEdg :: #{num_rev_edg} numSubEdg:: #{num_sub_edg}")
-
best_SV_VS_match = Array.new(num_rev_edg){Array.new}
-
cum_edge_match = 0.0
-
count = 0
-
max = 0.0
-
flag = 0
-
wnet = WordnetBasedSimilarity.new
-
for i in (0..num_rev_edg - 1)
-
if(!rev[i].nil? and rev[i].in_vertex.node_id != -1 and rev[i].out_vertex.node_id != -1)
-
#skipping frequent word
-
if(wnet.is_frequent_word(rev[i].in_vertex.name) and wnet.is_frequent_word(rev[i].out_vertex.name))
-
next
-
end
-
for j in (0..num_sub_edg - 1)
-
if(!subm[j].nil? and subm[j].in_vertex.node_id != -1 and subm[j].out_vertex.node_id != -1)
-
#checking if the subm token is a frequent word
-
if(wnet.is_frequent_word(subm[j].in_vertex.name) and wnet.is_frequent_word(subm[j].out_vertex.name))
-
next
-
end
-
if(rev[i].in_vertex.type == subm[j].out_vertex.type and rev[i].out_vertex.type == subm[j].in_vertex.type)
-
#taking each match separately because one or more of the terms may be a frequent word, for which no @vertex_match exists!
-
sum = 0.0
-
cou = 0
-
if(!@vertex_match[rev[i].in_vertex.node_id][subm[j].out_vertex.node_id].nil?)
-
sum = sum + @vertex_match[rev[i].in_vertex.node_id][subm[j].out_vertex.node_id]
-
cou +=1
-
end
-
if(!@vertex_match[rev[i].out_vertex.node_id][subm[j].in_vertex.node_id].nil?)
-
sum = sum + @vertex_match[rev[i].out_vertex.node_id][subm[j].in_vertex.node_id]
-
cou +=1
-
end
-
-
if(cou > 0)
-
best_SV_VS_match[i][j] = sum.to_f/cou.to_f
-
else
-
best_SV_VS_match[i][j] = 0.0
-
end
-
-
flag = 1
-
if(best_SV_VS_match[i][j] > max)
-
max = best_SV_VS_match[i][j]
-
end
-
end
-
end #end of the if condition
-
end #end of the for loop for the submission edges
-
-
if(flag != 0)#if the review edge had any submission edges with which it was matched, since not all S-V edges might have corresponding V-O edges to match with
-
# puts("**** Best match for:: #{rev[i].in_vertex.name} - #{rev[i].out_vertex.name}-- #{max}")
-
cum_edge_match = cum_edge_match + max
-
count+=1
-
max = 0.0 #re-initialize
-
flag = 0
-
end
-
-
end #end of the if condition
-
end #end of the for loop for the review
-
-
avg_match = 0.0
-
if(count > 0)
-
avg_match = cum_edge_match.to_f/count.to_f
-
end
-
return avg_match
-
end #end of the method
-
#------------------------------------------#------------------------------------------
-
=begin
-
DIFFERENT TYPE COMPARISON!!
-
* Compares the edges from across the two graphs to identify matches and quantify various metrics
-
* compare SUBJECT-VERB edges with VERB-OBJECT matches and vice-versa
-
* SUBJECT-VERB, VERB-SUBJECT, OBJECT-VERB, VERB-OBJECT comparisons are done!
-
=end
-
1
def compare_edges_diff_types(rev, subm, num_rev_edg, num_sub_edg)
-
# puts("*****Inside compareEdgesDiffTypes :: numRevEdg :: #{num_rev_edg} numSubEdg:: #{num_sub_edg}")
-
best_SV_VS_match = Array.new(num_rev_edg){Array.new}
-
cum_edge_match = 0.0
-
count = 0
-
max = 0.0
-
flag = 0
-
wnet = WordnetBasedSimilarity.new
-
for i in (0..num_rev_edg - 1)
-
if(!rev[i].nil? and rev[i].in_vertex.node_id != -1 and rev[i].out_vertex.node_id != -1)
-
#skipping edges with frequent words for vertices
-
if(wnet.is_frequent_word(rev[i].in_vertex.name) and wnet.is_frequent_word(rev[i].out_vertex.name))
-
next
-
end
-
#identifying best match for edges
-
for j in (0..num_sub_edg - 1)
-
if(!subm[j].nil? and subm[j].in_vertex.node_id != -1 and subm[j].out_vertex.node_id != -1)
-
#checking if the subm token is a frequent word
-
if(wnet.is_frequent_word(subm[j].in_vertex.name) and wnet.is_frequent_word(subm[j].out_vertex.name))
-
next
-
end
-
#for S-V with S-V or V-O with V-O
-
if(rev[i].in_vertex.type == subm[j].in_vertex.type and rev[i].out_vertex.type == subm[j].out_vertex.type)
-
#taking each match separately because one or more of the terms may be a frequent word, for which no @vertex_match exists!
-
sum = 0.0
-
cou = 0
-
if(!@vertex_match[rev[i].in_vertex.node_id][subm[j].out_vertex.node_id].nil?)
-
sum = sum + @vertex_match[rev[i].in_vertex.node_id][subm[j].out_vertex.node_id]
-
cou +=1
-
end
-
if(!@vertex_match[rev[i].out_vertex.node_id][subm[j].in_vertex.node_id].nil?)
-
sum = sum + @vertex_match[rev[i].out_vertex.node_id][subm[j].in_vertex.node_id]
-
cou +=1
-
end
-
if(cou > 0)
-
best_SV_VS_match[i][j] = sum.to_f/cou.to_f
-
else
-
best_SV_VS_match[i][j] = 0.0
-
end
-
#-- Vertex and SRL
-
best_SV_VS_match[i][j] = best_SV_VS_match[i][j]/ compare_labels(rev[i], subm[j])
-
flag = 1
-
if(best_SV_VS_match[i][j] > max)
-
max = best_SV_VS_match[i][j]
-
end
-
#for S-V with V-O or V-O with S-V
-
elsif(rev[i].in_vertex.type == subm[j].out_vertex.type and rev[i].out_vertex.type == subm[j].in_vertex.type)
-
#taking each match separately because one or more of the terms may be a frequent word, for which no @vertex_match exists!
-
sum = 0.0
-
cou = 0
-
if(!@vertex_match[rev[i].in_vertex.node_id][subm[j].in_vertex.node_id].nil?)
-
sum = sum + @vertex_match[rev[i].in_vertex.node_id][subm[j].in_vertex.node_id]
-
cou +=1
-
end
-
if(!@vertex_match[rev[i].out_vertex.node_id][subm[j].out_vertex.node_id].nil?)
-
sum = sum + @vertex_match[rev[i].out_vertex.node_id][subm[j].out_vertex.node_id]
-
cou +=1
-
end
-
if(cou > 0)
-
best_SV_VS_match[i][j] = sum.to_f/cou.to_f
-
else
-
best_SV_VS_match[i][j] =0.0
-
end
-
flag = 1
-
if(best_SV_VS_match[i][j] > max)
-
max = best_SV_VS_match[i][j]
-
end
-
end
-
end #end of the if condition
-
end #end of the for loop for submission edges
-
-
if(flag != 0) #if the review edge had any submission edges with which it was matched, since not all S-V edges might have corresponding V-O edges to match with
-
# puts("**** Best match for:: #{rev[i].in_vertex.name} - #{rev[i].out_vertex.name} -- #{max}")
-
cum_edge_match = cum_edge_match + max
-
count+=1
-
max = 0.0 #re-initialize
-
flag = 0
-
end
-
end #end of if condition
-
end #end of for loop for review edges
-
-
avg_match = 0.0
-
if(count > 0)
-
avg_match = cum_edge_match.to_f/ count.to_f
-
end
-
return avg_match
-
end #end of the method
-
#------------------------------------------#------------------------------------------
-
-
1
def compare_SVO_edges(rev, subm, num_rev_edg, num_sub_edg)
-
# puts("***********Inside compare SVO edges numRevEdg:: #{num_rev_edg} numSubEdg:: #{num_sub_edg}")
-
best_SVO_SVO_edges_match = Array.new(num_rev_edg){Array.new}
-
cum_double_edge_match = 0.0
-
count = 0
-
max = 0.0
-
flag = 0
-
wnet = WordnetBasedSimilarity.new
-
for i in (0..num_rev_edg - 1)
-
if(!rev[i].nil? and !rev[i+1].nil? and rev[i].in_vertex.node_id != -1 and rev[i].out_vertex.node_id != -1 and
-
rev[i+1].out_vertex.node_id != -1 and rev[i].out_vertex == rev[i+1].in_vertex)
-
#skipping edges with frequent words for vertices
-
if(wnet.is_frequent_word(rev[i].in_vertex.name) and wnet.is_frequent_word(rev[i].out_vertex.name) and wnet.is_frequent_word(rev[i+1].out_vertex.name))
-
next
-
end
-
#best match
-
for j in (0..num_sub_edg - 1)
-
if(!subm[j].nil? and !subm[j+1].nil? and subm[j].in_vertex.node_id != -1 and subm[j].out_vertex.node_id != -1 and
-
subm[j+1].out_vertex.node_id != -1 and subm[j].out_vertex == subm[j+1].in_vertex)
-
#checking if the subm token is a frequent word
-
if(wnet.is_frequent_word(subm[j].in_vertex.name) and wnet.is_frequent_word(subm[j].out_vertex.name))
-
next
-
end
-
#making sure the types are the same during comparison
-
if(rev[i].in_vertex.type == subm[j].in_vertex.type and rev[i].out_vertex.type == subm[j].out_vertex.type and
-
rev[i+1].out_vertex.type == subm[j+1].out_vertex.type)
-
#taking each match separately because one or more of the terms may be a frequent word, for which no @vertex_match exists!
-
sum = 0.0
-
cou = 0
-
if(!@vertex_match[rev[i].in_vertex.node_id][subm[j].in_vertex.node_id].nil?)
-
sum = sum + @vertex_match[rev[i].in_vertex.node_id][subm[j].in_vertex.node_id]
-
cou +=1
-
end
-
if(!@vertex_match[rev[i].out_vertex.node_id][subm[j].out_vertex.node_id].nil?)
-
sum = sum + @vertex_match[rev[i].out_vertex.node_id][subm[j].out_vertex.node_id]
-
cou +=1
-
end
-
if(!@vertex_match[rev[i+1].out_vertex.node_id][subm[j+1].out_vertex.node_id].nil?)
-
sum = sum + @vertex_match[rev[i+1].out_vertex.node_id][subm[j+1].out_vertex.node_id]
-
cou +=1
-
end
-
#-- Only Vertex match
-
if(cou > 0)
-
best_SVO_SVO_edges_match[i][j] = sum.to_f/cou.to_f
-
else
-
best_SVO_SVO_edges_match[i][j] = 0.0
-
end
-
#-- Vertex and SRL
-
best_SVO_SVO_edges_match[i][j] = best_SVO_SVO_edges_match[i][j].to_f/ compare_labels(rev[i], subm[j]).to_f
-
best_SVO_SVO_edges_match[i][j] = best_SVO_SVO_edges_match[i][j].to_f/ compare_labels(rev[i+1], subm[j+1]).to_f
-
#-- Only SRL
-
if(best_SVO_SVO_edges_match[i][j] > max)
-
max = best_SVO_SVO_edges_match[i][j]
-
end
-
flag = 1
-
end
-
end #end of 'if' condition
-
end #end of 'for' loop for 'j'
-
-
if(flag != 0) #if the review edge had any submission edges with which it was matched, since not all S-V edges might have corresponding V-O edges to match with
-
# puts("**** Best match for:: #{rev[i].in_vertex.name} - #{rev[i].out_vertex.name} - #{rev[i+1].out_vertex.name} -- #{max}")
-
cum_double_edge_match = cum_double_edge_match + max
-
count+=1
-
max = 0.0 #re-initialize
-
flag = 0
-
end
-
end #end of 'if' condition
-
end #end of 'for' loop for 'i'
-
-
avg_match = 0.0
-
if(count > 0)
-
avg_match = cum_double_edge_match.to_f/ count.to_f
-
end
-
return avg_match
-
end
-
#------------------------------------------#------------------------------------------
-
-
1
def compare_SVO_diff_syntax(rev, subm, num_rev_edg, num_sub_edg)
-
# puts("***********Inside compare SVO edges with syntax difference numRevEdg:: #{num_rev_edg} numSubEdg:: #{num_sub_edg}")
-
best_SVO_OVS_edges_match = Array.new(num_rev_edg){ Array.new}
-
cum_double_edge_match = 0.0
-
count = 0
-
max = 0.0
-
flag = 0
-
wnet = WordnetBasedSimilarity.new
-
for i in (0..num_rev_edg - 1)
-
if(!rev[i].nil? and !rev[i+1].nil? and rev[i].in_vertex.node_id != -1 and rev[i].out_vertex.node_id != -1 and
-
rev[i+1].out_vertex.node_id != -1 and rev[i].out_vertex == rev[i+1].in_vertex)
-
#skipping edges with frequent words for vertices
-
if(wnet.is_frequent_word(rev[i].in_vertex.name) and wnet.is_frequent_word(rev[i].out_vertex.name) and wnet.is_frequent_word(rev[i+1].out_vertex.name))
-
next
-
end
-
-
for j in (0..num_sub_edg - 1)
-
if(!subm[j].nil? and !subm[j+1].nil? and subm[j].in_vertex.node_id != -1 and subm[j].out_vertex.node_id != -1 and subm[j+1].out_vertex.node_id != -1 and subm[j].out_vertex == subm[j+1].in_vertex)
-
#making sure the types are the same during comparison
-
if(rev[i].in_vertex.type == subm[j+1].out_vertex.type and rev[i].out_vertex.type == subm[j].out_vertex.type and
-
rev[i+1].out_vertex.type == subm[j].in_vertex.type)
-
#taking each match separately because one or more of the terms may be a frequent word, for which no @vertex_match exists!
-
sum = 0.0
-
cou = 0
-
if(!@vertex_match[rev[i].in_vertex.node_id][subm[j+1].out_vertex.node_id].nil?)
-
sum = sum + @vertex_match[rev[i].in_vertex.node_id][subm[j+1].out_vertex.node_id]
-
cou +=1
-
end
-
if(!@vertex_match[rev[i].out_vertex.node_id][subm[j].out_vertex.node_id].nil?)
-
sum = sum + @vertex_match[rev[i].out_vertex.node_id][subm[j].out_vertex.node_id]
-
cou +=1
-
end
-
if(!@vertex_match[rev[i+1].out_vertex.node_id][subm[j].in_vertex.node_id].nil?)
-
sum = sum + @vertex_match[rev[i+1].out_vertex.node_id][subm[j].in_vertex.node_id]
-
cou +=1
-
end
-
#comparing s-v-o (from review) with o-v-s (from submission)
-
if(cou > 0)
-
best_SVO_OVS_edges_match[i][j] = sum.to_f/cou.to_f
-
else
-
best_SVO_OVS_edges_match[i][j] = 0.0
-
end
-
flag = 1
-
if(best_SVO_OVS_edges_match[i][j] > max)
-
max = best_SVO_OVS_edges_match[i][j]
-
end
-
end
-
end #end of 'if' condition
-
end #end of 'for' loop for 'j'
-
if(flag != 0)#if the review edge had any submission edges with which it was matched, since not all S-V edges might have corresponding V-O edges to match with
-
# puts("**** Best match for:: #{rev[i].in_vertex.name} - #{rev[i].out_vertex.name} - #{rev[i+1].out_vertex.name}-- #{max}")
-
cum_double_edge_match = cum_double_edge_match + max
-
count+=1
-
max = 0.0 #re-initialize
-
flag = 0
-
end
-
-
end #end of if condition
-
end #end of for loop for 'i'
-
-
avg_match = 0.0
-
if(count > 0)
-
avg_match = cum_double_edge_match.to_f / count.to_f
-
end
-
return avg_match
-
end #end of method
-
#------------------------------------------#------------------------------------------
-
=begin
-
SR Labels and vertex matches are given equal importance
-
* Problem is even if the vertices didn't match, the SRL labels would cause them to have a high similarity.
-
* Consider "boy - said" and "chocolate - melted" - these edges have NOMATCH for vertices, but both edges have the same label "SBJ" and would get an EXACT match,
-
* resulting in an avg of 3! This cant be right!
-
* We therefore use the labels to only decrease the match value found from vertices, i.e., if the labels were different.
-
* Match value will be left as is, if the labels were the same.
-
=end
-
1
def compare_labels(edge1, edge2)
-
result = EQUAL
-
if(!edge1.label.nil? and !edge2.label .nil?)
-
if(edge1.label.downcase == edge2.label.downcase)
-
result = EQUAL #divide by 1
-
else
-
result = DISTINCT #divide by 2
-
end
-
elsif((!edge1.label.nil? and !edge2.label.nil?) or (edge1.label.nil? and !edge2.label.nil? )) #if only one of the labels was null
-
result = DISTINCT
-
elsif(edge1.label.nil? and edge2.label.nil?) #if both labels were null!
-
result = EQUAL
-
end
-
return result
-
end # end of method
-
end
-
1
class Edge
-
1
attr_accessor :edgeID, :type, :name, :index, :in_vertex, :out_vertex, :edge_match, :average_match, :frequency, :label
-
-
1
def initialize(edge_name, edge_type)
-
@name = edge_name
-
@type = edge_type #1 - verb, 2 - adjective, 3-adverb
-
@average_match = 0.0 #initializing match to 0
-
@frequency = 0
-
#initializing the number of matches for each metric value to 0
-
@edge_match = Array.new
-
@edge_match = [0, 0, 0, 0, 0]
-
end
-
end
-
1
require 'automated_metareview/sentence_state'
-
1
require 'automated_metareview/edge'
-
1
require 'automated_metareview/vertex'
-
-
1
class GraphGenerator
-
#include SentenceState
-
#creating accessors for the instance variables
-
1
attr_accessor :vertices, :num_vertices, :edges, :num_edges, :pipeline, :pos_tagger
-
-
# #global variables
-
# $vertices = Array.new
-
# $edges = Array.new
-
-
=begin
-
* generates the graph for the given review text and
-
* INPUT: an array of sentences for a review or a submission. Every row in 'text' contains one sentence.
-
* type - tells you if it was a review or s submission
-
* type = 1 - submission/past review
-
* type = 2 - new review
-
=end
-
1
def generate_graph(text, pos_tagger, coreNLPTagger, forRelevance, forPatternIdentify)
-
#initializing common arrays
-
@vertices = Array.new
-
@num_vertices = 0
-
@edges = Array.new
-
@num_edges = 0
-
-
@pos_tagger = pos_tagger #part of speech tagger
-
@pipeline = coreNLPTagger #dependency parsing
-
#iterate through the sentences in the text
-
for i in (0..text.length-1)
-
if(text[i].empty? or text[i] == "" or text[i].split(" ").empty?)
-
next
-
end
-
unTaggedString = text[i].split(" ")
-
# puts "UnTagged String:: #{unTaggedString}"
-
taggedString = @pos_tagger.get_readable(text[i])
-
# puts "taggedString:: #{taggedString}"
-
-
#Initializing some arrays
-
nouns = Array.new
-
nCount = 0
-
verbs = Array.new
-
vCount = 0
-
adjectives = Array.new
-
adjCount = 0
-
adverbs = Array.new
-
advCount = 0
-
-
parents = Array.new
-
labels = Array.new
-
-
#------------------------------------------#------------------------------------------
-
#finding parents
-
parents = find_parents(text[i])
-
parentCounter = 0
-
#------------------------------------------#------------------------------------------
-
#finding parents
-
labels = find_labels(text[i])
-
labelCounter = 0
-
#------------------------------------------#------------------------------------------
-
#find state
-
sstate = SentenceState.new
-
states_array = sstate.identify_sentence_state(taggedString)
-
states_counter = 0
-
state = states_array[states_counter]
-
states_counter += 1
-
#------------------------------------------#------------------------------------------
-
-
taggedString = taggedString.split(" ")
-
prevType = nil #initlializing the prevyp
-
-
#iterate through the tokens
-
for j in (0..taggedString.length-1)
-
taggedToken = taggedString[j]
-
plainToken = taggedToken[0...taggedToken.index("/")].to_s
-
posTag = taggedToken[taggedToken.index("/")+1..taggedToken.length].to_s
-
#ignore periods
-
if(plainToken == "." or taggedToken.include?("/POS") or (taggedToken.index("/") == taggedToken.length()-1) or (taggedToken.index("/") == taggedToken.length()-2))#this is for strings containinig "'s" or without POS
-
next
-
end
-
-
#SETTING STATE
-
#since the CC or IN are part of the following sentence segment, we set the STATE for that segment when we see a CC or IN
-
if(taggedToken.include?("/CC"))#{//|| ps.contains("/IN")
-
state = states_array[states_counter]
-
states_counter+=1
-
end
-
# puts("**Value:: #{plainToken} LabelCounter:: #{labelCounter} ParentCounter:: #{parentCounter} POStag:: #{posTag} .. state = #{state}")
-
-
#------------------------------------------
-
#if the token is a noun
-
if(taggedToken.include?("NN") or taggedToken.include?("PRP") or taggedToken.include?("IN") or taggedToken.include?("/EX") or taggedToken.include?("WP"))
-
#either add on to a previous vertex or create a brand new noun vertex
-
if(prevType == NOUN) #adding to a previous noun vertex
-
nCount -= 1 #decrement, since we are accessing a previous noun vertex
-
prevVertex = search_vertices(@vertices, nouns[nCount], i) #fetching the previous vertex
-
nouns[nCount] = nouns[nCount].to_s + " " + plainToken #concatenating with contents of the previous noun vertex
-
#checking if the previous noun concatenated with "s" already exists among the vertices
-
if((nounVertex = search_vertices(@vertices, nouns[nCount], i)) == nil)
-
prevVertex.name = prevVertex.name.to_s + " " + plainToken #concatenating the nouns
-
nounVertex = prevVertex #the current concatenated vertex will be considered
-
if(labels[labelCounter] != "NMOD" or labels[labelCounter] != "PMOD")#resetting labels for the concatenated vertex
-
nounVertex.label = labels[labelCounter]
-
end
-
#fAppendedVertex = 1
-
end#if the vertex already exists, just use nounVertex - the returned vertex for ops.
-
else #if the previous token is not a noun, create a brand new vertex
-
nouns[nCount] = plainToken #this is checked for later on
-
nounVertex = search_vertices(@vertices, plainToken, i)
-
if(nounVertex == nil) #the string doesn't already exist
-
@vertices[@num_vertices] = Vertex.new(nouns[nCount], NOUN, i, state, labels[labelCounter], parents[parentCounter], posTag)
-
nounVertex = @vertices[@num_vertices] #the newly formed vertex will be considered
-
@num_vertices+=1
-
end
-
end #end of if prevType was noun
-
remove_redundant_vertices(nouns[nCount], i)
-
nCount+=1 #increment nCount for a new noun vertex just created (or existing previous vertex appended with new text)
-
-
#checking if a noun existed before this one and if the adjective was attached to that noun.
-
#if an adjective was found earlier, we add a new edge
-
if(prevType == ADJ)
-
#set previous noun's property to null, if it was set, if there is a noun before the adjective
-
if(nCount > 1)
-
v1 = search_vertices(@vertices, nouns[nCount-2], i) #fetching the previous noun, the one before the current noun (therefore -2)
-
v2 = search_vertices(@vertices, adjectives[adjCount-1], i) #fetching the previous adjective
-
#if such an edge exists - DELETE IT - search_edges_to_set_null() returns the position in the array at which such an edge exists
-
if(!v1.nil? and !v2.nil? and (e = search_edges_to_set_null(@edges, v1, v2, i)) != -1) #-1 is when no such edge exists
-
@edges[e] = nil #setting the edge to null
-
#if @num_edges had been previously incremented, decrement it
-
if(@num_edges > 0)
-
@num_edges-=1 #deducting an edge count
-
end
-
end
-
end
-
#if this noun vertex was encountered for the first time, nCount < 1,
-
#so do adding of edge outside the if condition
-
#add a new edge with v1 as the adjective and v2 as the new noun
-
v1 = search_vertices(@vertices, adjectives[adjCount-1], i)
-
v2 = nounVertex #the noun vertex that was just created
-
#if such an edge did not already exist
-
if(!v1.nil? and !v2.nil? and (e = search_edges(@edges, v1, v2, i)) == -1)
-
@edges[@num_edges] = Edge.new("noun-property",VERB)
-
@edges[@num_edges].in_vertex = v1
-
@edges[@num_edges].out_vertex = v2
-
@edges[@num_edges].index = i
-
@num_edges+=1
-
#since an edge was just added we try to check if there exist any redundant edges that can be removed
-
remove_redundant_edges(v1, v2, i)
-
end
-
end
-
#a noun has been found and has established a verb as an in_vertex and such an edge doesnt already previously exist
-
if(vCount > 0) #and fAppendedVertex == 0
-
#add edge only when a fresh vertex is created not when existing vertex is appended to
-
v1 = search_vertices(@vertices, verbs[vCount-1], i)
-
v2 = nounVertex
-
#if such an edge does not already exist add it
-
if(!v1.nil? and !v2.nil? and (e = search_edges(@edges,v1, v2, i)) == -1)
-
@edges[@num_edges] = Edge.new("verb", VERB)
-
@edges[@num_edges].in_vertex = v1 #for vCount = 0
-
@edges[@num_edges].out_vertex = v2
-
@edges[@num_edges].index = i
-
@num_edges+=1
-
#since an edge was just added we try to check if there exist any redundant edges that can be removed
-
remove_redundant_edges(v1, v2, i)
-
end
-
end
-
prevType = NOUN
-
#------------------------------------------
-
-
#if the string is an adjective
-
#adjectives are vertices but they are not connected by an edge to the nouns, instead they are the noun's properties
-
elsif(taggedToken.include?("/JJ"))
-
adjective = nil
-
if(prevType == ADJ) #combine the adjectives
-
# puts("PREV ADJ here:: #{plainToken}")
-
if(adjCount >= 1)
-
adjCount = adjCount - 1
-
prevVertex = search_vertices(@vertices, adjectives[adjCount], i) #fetching the previous vertex
-
adjectives[adjCount] = adjectives[adjCount] + " " + plainToken
-
#if the concatenated vertex didn't already exist
-
if((adjective = search_vertices(@vertices, adjectives[adjCount], i)).nil?)
-
prevVertex.name = prevVertex.name+" "+plainToken
-
adjective = prevVertex #set it as "adjective" for further execution
-
if(labels[labelCounter] != "NMOD" or labels[labelCounter] != "PMOD") #resetting labels for the concatenated vertex
-
adjective.label = labels[labelCounter]
-
end
-
end
-
end
-
else #new adjective vertex
-
adjectives[adjCount] = plainToken
-
if((adjective = search_vertices(@vertices, plainToken, i)).nil?) #the string doesn't already exist
-
@vertices[@num_vertices] = Vertex.new(adjectives[adjCount], ADJ, i, state, labels[labelCounter], parents[parentCounter], posTag)
-
adjective = @vertices[@num_vertices]
-
@num_vertices+=1
-
end
-
end
-
remove_redundant_vertices(adjectives[adjCount], i)
-
adjCount+=1 #incrementing, since a new adjective was created or an existing one updated.
-
-
#by default associate the adjective with the previous/latest noun and if there is a noun following it immediately, then remove the property from the older noun (done under noun condition)
-
if(nCount > 0) #gets the previous noun to form the edge
-
v1 = search_vertices(@vertices, nouns[nCount-1], i)
-
v2 = adjective #the current adjective vertex
-
#if such an edge does not already exist add it
-
if(!v1.nil? and !v2.nil? and (e = search_edges(@edges, v1, v2, i)) == -1)
-
# puts "** Adding noun-adj edge .. #{v1.name} - #{v2.name}"
-
@edges[@num_edges] = Edge.new("noun-property",VERB)
-
@edges[@num_edges].in_vertex = v1
-
@edges[@num_edges].out_vertex = v2
-
@edges[@num_edges].index = i
-
@num_edges+=1
-
#since an edge was just added we try to check if there exist any redundant edges that can be removed
-
remove_redundant_edges(v1, v2, i)
-
end
-
end
-
prevType = ADJ
-
#end of if condition for adjective
-
#------------------------------------------
-
-
#if the string is a verb or a modal//length condition for verbs is, be, are...
-
elsif(taggedToken.include?("/VB") or taggedToken.include?("MD"))
-
verbVertex = nil
-
if(prevType == VERB) #combine the verbs
-
vCount = vCount - 1
-
prevVertex = search_vertices(@vertices, verbs[vCount], i) #fetching the previous vertex
-
verbs[vCount] = verbs[vCount] + " " + plainToken
-
#if the concatenated vertex didn't already exist
-
if((verbVertex = search_vertices(@vertices, verbs[vCount], i)) == nil)
-
prevVertex.name = prevVertex.name + " " + plainToken
-
verbVertex = prevVertex #concatenated vertex becomes the new verb vertex
-
if(labels[labelCounter] != "NMOD" or labels[labelCounter] != "PMOD")#resetting labels for the concatenated vertex
-
verbVertex.label = labels[labelCounter]
-
end
-
end
-
else
-
verbs[vCount] = plainToken
-
if((verbVertex = search_vertices(@vertices, plainToken, i)) == nil)
-
@vertices[@num_vertices] = Vertex.new(plainToken, VERB, i, state, labels[labelCounter], parents[parentCounter], posTag)
-
verbVertex = @vertices[@num_vertices] #newly created verb vertex will be considered in the future
-
@num_vertices+=1
-
end
-
end
-
remove_redundant_vertices(verbs[vCount], i)
-
vCount+=1
-
-
#if an adverb was found earlier, we set that as the verb's property
-
if(prevType == ADV)
-
#set previous verb's property to null, if it was set, if there is a verb following the adverb
-
if(vCount > 1)
-
v1 = search_vertices(@vertices, verbs[vCount-2], i) #fetching the previous verb, the one before the current one (hence -2)
-
v2 = search_vertices(@vertices, adverbs[advCount-1], i) #fetching the previous adverb
-
#if such an edge exists - DELETE IT
-
if(!v1.nil? and !v2.nil? and (e = search_edges_to_set_null(@edges, v1, v2, i)) != -1)
-
@edges[e] = nil #setting the edge to null
-
if(@num_edges > 0)
-
@num_edges-=1 #deducting an edge count
-
end
-
end
-
end
-
#if this verb vertex was encountered for the first time, vCount < 1,
-
#so do adding of edge outside the if condition
-
#add a new edge with v1 as the adverb and v2 as the new verb
-
v1 = search_vertices(@vertices, adverbs[advCount-1], i)
-
v2 = verbVertex
-
#if such an edge did not already exist
-
if(!v1.nil? and !v2.nil? and (e = search_edges(@edges, v1, v2, i)) == -1)
-
@edges[@num_edges] = Edge.new("verb-property",VERB)
-
@edges[@num_edges].in_vertex = v1
-
@edges[@num_edges].out_vertex = v2
-
@edges[@num_edges].index = i
-
@num_edges+=1
-
#since an edge was just added we try to check if there exist any redundant edges that can be removed
-
remove_redundant_edges(v1, v2, i)
-
end
-
end
-
-
#making the previous noun, one of the vertices of the verb edge
-
if(nCount > 0) #and fAppendedVertex == 0
-
#gets the previous noun to form the edge
-
v1 = search_vertices(@vertices, nouns[nCount-1], i)
-
v2 = verbVertex
-
#if such an edge does not already exist add it
-
if(!v1.nil? and !v2.nil? and (e = search_edges(@edges, v1, v2, i)) == -1)
-
@edges[@num_edges] = Edge.new("verb",VERB)
-
@edges[@num_edges].in_vertex = v1 #for nCount = 0;
-
@edges[@num_edges].out_vertex = v2 #the verb
-
@edges[@num_edges].index = i
-
@num_edges+=1
-
#since an edge was just added we try to check if there exist any redundant edges that can be removed
-
remove_redundant_edges(v1, v2, i)
-
end
-
end
-
prevType = VERB
-
#------------------------------------------
-
#if the string is an adverb
-
elsif(taggedToken.include?("RB"))
-
adverb = nil
-
if(prevType == ADV) #appending to existing adverb
-
if(advCount >= 1)
-
advCount = advCount - 1
-
end
-
prevVertex = search_vertices(@vertices, adverbs[advCount], i) #fetching the previous vertex
-
adverbs[advCount] = adverbs[advCount] + " " + plainToken
-
#if the concatenated vertex didn't already exist
-
if((adverb = search_vertices(@vertices, adverbs[advCount], i)) == nil)
-
prevVertex.name = prevVertex.name + " " + plainToken
-
adverb = prevVertex #setting it as "adverb" for further computation
-
if(labels[labelCounter] != "NMOD" or labels[labelCounter] != "PMOD") #resetting labels for the concatenated vertex
-
adverb.label = labels[labelCounter]
-
end
-
end
-
else #else creating a new vertex
-
adverbs[advCount] = plainToken
-
if((adverb = search_vertices(@vertices, plainToken, i)) == nil)
-
@vertices[@num_vertices] = Vertex.new(adverbs[advCount], ADV, i, state, labels[labelCounter], parents[parentCounter], posTag);
-
adverb = @vertices[@num_vertices]
-
@num_vertices+=1
-
end
-
end
-
remove_redundant_vertices(adverbs[advCount], i)
-
advCount+=1
-
-
#by default associate it with the previous/latest verb and if there is a verb following it immediately, then remove the property from the verb
-
if(vCount > 0) #gets the previous verb to form a verb-adverb edge
-
v1 = search_vertices(@vertices, verbs[vCount-1], i)
-
v2 = adverb
-
#if such an edge does not already exist add it
-
if(!v1.nil? and !v2.nil? && (e = search_edges(@edges, v1, v2, i)) == -1)
-
@edges[@num_edges] = Edge.new("verb-property",VERB)
-
@edges[@num_edges].in_vertex = v1 #for nCount = 0;
-
@edges[@num_edges].out_vertex = v2 #the verb
-
@edges[@num_edges].index = i
-
@num_edges+=1
-
#since an edge was just added we try to check if there exist any redundant edges that can be removed
-
remove_redundant_edges(v1, v2, i)
-
end
-
end
-
prevType = ADV
-
#end of if condition for adverb
-
end #end of if condition
-
#------------------------------------------
-
#incrementing counters for labels and parents
-
labelCounter+=1
-
parentCounter+=1
-
end #end of the for loop for the tokens
-
#puts "here outside the for loop for tokens"
-
nouns = nil
-
verbs = nil
-
adjectives = nil
-
adverbs = nil
-
end #end of number of sentences in the text
-
-
@num_vertices = @num_vertices - 1 #since as a counter it was 1 ahead of the array's contents
-
@num_edges = @num_edges - 1 #same reason as for num_vertices
-
set_semantic_labels_for_edges
-
#print_graph(@edges, @vertices)
-
# puts("Number of edges:: #{@num_edges}")
-
# puts("Number of vertices:: #{@num_vertices}")
-
return @num_edges
-
end #end of the graphGenerate method
-
-
#------------------------------------------#------------------------------------------#------------------------------------------
-
-
1
def search_vertices(list, s, index)
-
for i in (0..list.length-1)
-
if(!list[i].nil? and !s.nil?)
-
#if the vertex exists and in the same sentence (index)
-
if(list[i].name.casecmp(s) == 0 and list[i].index == index)
-
# puts("***** search_vertices:: Returning:: #{s}")
-
return list[i]
-
end
-
end
-
end
-
# puts("***** search_vertices:: Returning nil")
-
return nil
-
end #end of the search_vertices method
-
-
#------------------------------------------#------------------------------------------#------------------------------------------
-
-
=begin
-
NULLIFY ALL VERTICES CONTAINING "ONLY SUBSTRINGS" (and not exact matches) OF THIS VERTEX IN THE SAME SENTENCE (verts[j].index == index)
-
And reset the @vertices array with non-null elements.
-
=end
-
1
def remove_redundant_vertices(s, index)
-
# puts "**** remove_redundant_vertices:: string #{s}"
-
j = @num_vertices - 1
-
verts = @vertices
-
while j >= 0
-
if(!verts[j].nil? and verts[j].index == index and s.casecmp(verts[j].name) != 0 and
-
(s.downcase.include?(verts[j].name.downcase) and verts[j].name.length > 1))
-
#the last 'length' condition is added so as to prevent "I" (an indiv. vertex) from being replaced by nil
-
# puts "*** string index = #{index}... verts[j].index = #{verts[j].index}"
-
# puts "**** remove_redundant_vertices setting #{verts[j].name} to nil!"
-
#search through all the edges and set those with this vertex as in-out- vertex to null
-
if(!@edges.nil?)
-
for i in 0..@edges.length - 1
-
edge = @edges[i]
-
if(!edge.nil? and (edge.in_vertex == verts[j] or edge.out_vertex == verts[j]))
-
# puts "edge #{edge.in_vertex.name} - #{edge.out_vertex.name}"
-
@edges[i] = nil #setting that edge to nil
-
end
-
end
-
end
-
#finally setting the vertex to null
-
verts[j] = nil
-
end
-
j-=1
-
end #end of while loop
-
-
# puts "**** remove_redundant_vertices Old @num_vertices:: #{@num_vertices}"
-
#recreating the vertices array without the nil values
-
counter = 0
-
vertices_array = Array.new
-
for i in (0..verts.length-1)
-
vertex = verts[i]
-
if(!vertex.nil?)
-
vertices_array << vertex
-
counter+=1
-
end
-
end
-
@vertices = vertices_array
-
@num_vertices = counter+1 #since @num_vertices is always one advanced of the last vertex
-
end
-
-
#------------------------------------------#------------------------------------------#------------------------------------------
-
-
=begin
-
Checks to see if an edge between vertices "in" and "out" exists.
-
true - if an edge exists and false - if an edge doesn't exist
-
edge[] list, vertex in, vertex out, int index
-
=end
-
1
def search_edges(list, in_vertex, out, index)
-
edgePos = -1
-
if(list.nil?)#if the list is null
-
return edgePos
-
end
-
-
for i in (0..list.length-1)
-
if(!list[i].nil? and !list[i].in_vertex.nil? and !list[i].out_vertex.nil?)
-
#checking for exact match with an edge
-
if(((list[i].in_vertex.name.casecmp(in_vertex.name)==0 or list[i].in_vertex.name.include?(in_vertex.name)) and
-
(list[i].out_vertex.name.casecmp(out.name)==0 or list[i].out_vertex.name.include?(out.name))) or
-
((list[i].in_vertex.name.casecmp(out.name)==0 or list[i].in_vertex.name.include?(out.name)) and
-
(list[i].out_vertex.name.casecmp(in_vertex.name)==0 or list[i].out_vertex.name.include?(in_vertex.name))))
-
# puts("***** Found edge! : index:: #{index} list[i].index:: #{list[i].index}")
-
#if an edge was found
-
edgePos = i #returning its position in the array
-
#INCREMENT FREQUENCY IF THE EDGE WAS FOUND IN A DIFFERENT SENT. (CHECK BY MAINTAINING A TEXT NUMBER AND CHECKING IF THE NEW # IS DIFF FROM PREV #)
-
if(index != list[i].index)
-
list[i].frequency+=1
-
end
-
end
-
end
-
end #end of the for loop
-
return edgePos
-
end # end of searchdges
-
#------------------------------------------#------------------------------------------#------------------------------------------
-
-
1
def search_edges_to_set_null(list, in_vertex, out, index)
-
edgePos = -1
-
# puts("***** Searching edge to set to null:: #{in_vertex.name} - #{out.name} ... num_edges #{@num_edges}")
-
for i in 0..@num_edges - 1
-
if(!list[i].nil? and !list[i].in_vertex.nil? and !list[i].out_vertex.nil?)
-
# puts "comparing with #{list[i].in_vertex.name} - #{list[i].out_vertex.name}"
-
#puts "#{list[i].in_vertex.name.downcase == in_vertex.name.downcase} - #{list[i].out_vertex.name.downcase == out.name.downcase}"
-
#checking for exact match with an edge
-
if((list[i].in_vertex.name.downcase == in_vertex.name.downcase and list[i].out_vertex.name.downcase == out.name.downcase) or
-
(list[i].in_vertex.name.downcase == out.name.downcase and list[i].out_vertex.name.downcase == in_vertex.name.downcase))
-
#if an edge was found
-
edgePos = i #returning its position in the array
-
#INCREMENT FREQUENCY IF THE EDGE WAS FOUND IN A DIFFERENT SENT. (CHECK BY MAINTAINING A TEXT NUMBER AND CHECKING IF THE NEW # IS DIFF FROM PREV #)
-
if(index != list[i].index)
-
list[i].frequency+=1
-
end
-
end
-
end
-
end #end of the for loop
-
# puts("***** search_edges_to_set_null #{in_vertex.name} - #{out.name} returning:: #{edgePos}")
-
return edgePos
-
end # end of the method search_edges_to_set_null
-
#------------------------------------------#------------------------------------------#------------------------------------------
-
=begin
-
NULLIFY ALL EDGES CONTAINING "ONLY SUBSTRINGS" (and not exact matches) OF EITHER IN/OUT VERTICES IN THE SAME SENTENCE (verts[j].index == index)
-
And reset the @edges array with non-null elements.
-
=end
-
-
1
def remove_redundant_edges(in_vertex, out, index)
-
list = @edges
-
j = @num_edges - 1
-
while j >= 0 do
-
if(!list[j].nil? and list[j].index == index)
-
#when invertices are eq and out-verts are substrings or vice versa
-
if(in_vertex.name.casecmp(list[j].in_vertex.name) == 0 and out.name.casecmp(list[j].out_vertex.name) != 0 and out.name.downcase.include?(list[j].out_vertex.name.downcase))
-
# puts("FOUND out_vertex match for edge:: #{list[j].in_vertex.name} - #{list[j].out_vertex.name}")
-
list[j] = nil
-
#@num_edges-=1
-
#when in-vertices are only substrings and out-verts are equal
-
elsif(in_vertex.name.casecmp(list[j].in_vertex.name)!=0 and in_vertex.name.downcase.include?(list[j].in_vertex.name.downcase) and out.name.casecmp(list[j].out_vertex.name)==0)
-
# puts("FOUND in_vertex match for edge: #{list[j].in_vertex.name} - #{list[j].out_vertex.name}")
-
list[j] = nil
-
#@num_edges-=1
-
end
-
end
-
j-=1
-
end #end of the while loop
-
# puts "**** search_edges:: Old number #{@num_edges}"
-
#recreating the edges array without the nil values
-
counter = 0
-
edges_array = Array.new
-
list.each{
-
|edge|
-
if(!edge.nil?)
-
# puts "edge:: #{edge.in_vertex.name} - #{edge.out_vertex.name}"
-
edges_array << edge
-
counter+=1
-
end
-
}
-
@edges = edges_array
-
@num_edges = counter+1
-
# puts "**** search_edges:: New number of edges #{@num_edges}"
-
end
-
-
#------------------------------------------#------------------------------------------#------------------------------------------
-
1
def print_graph(edges, vertices)
-
puts("*** List of vertices::")
-
for j in (0..vertices.length-1)
-
if(!vertices[j].nil?)
-
puts("@@@ Vertex:: #{vertices[j].name}")
-
puts("*** Frequency:: #{vertices[j].frequency} State:: #{vertices[j].state}")
-
puts("*** Label:: #{vertices[j].label} Parent:: #{vertices[j].parent}")
-
end
-
end
-
puts("*******")
-
puts("*** List of edges::")
-
for j in (0..edges.length-1)
-
if(!edges[j].nil? and !edges[j].in_vertex.nil? and !edges[j].out_vertex.nil?)
-
puts("@@@ Edge:: #{edges[j].in_vertex.name} & #{edges[j].out_vertex.name}")
-
puts("*** Frequency:: #{edges[j].frequency} State:: #{edges[j].in_vertex.state} & #{edges[j].out_vertex.state}")
-
puts("*** Label:: #{edges[j].label}")
-
end
-
end
-
puts("--------------")
-
end #end of print_graph method
-
-
#------------------------------------------#------------------------------------------#------------------------------------------
-
#Identifying parents and labels for the vertices
-
1
def find_parents(t)
-
# puts "Inside find_parents.. text #{t}"
-
tp = TextPreprocessing.new
-
unTaggedString = t.split(" ")
-
parents = Array.new
-
# t = text[i]
-
t = StanfordCoreNLP::Text.new(t) #the same variable has to be passed into the Textx.new method
-
@pipeline.annotate(t)
-
#for each sentence identify theparsed form of the sentence
-
sentence = t.get(:sentences).toArray
-
parsed_sentence = sentence[0].get(:collapsed_c_c_processed_dependencies)
-
#puts "parsed sentence #{parsed_sentence}"
-
#iterating through the set of tokens and identifying each token's parent
-
#puts "unTaggedString.length #{unTaggedString.length}"
-
for j in (0..unTaggedString.length - 1)
-
#puts "unTaggedString[#{j}] #{unTaggedString[j]}"
-
if(tp.is_punct(unTaggedString[j]))
-
next
-
end
-
if(tp.contains_punct(unTaggedString[j]))
-
unTaggedString[j] = tp.contains_punct(unTaggedString[j])
-
# puts "unTaggedString #{unTaggedString[j]} and #{tp.contains_punct_bool(unTaggedString[j])}"
-
end
-
if(!unTaggedString[j].nil? and !tp.contains_punct_bool(unTaggedString[j]))
-
pat = parsed_sentence.getAllNodesByWordPattern(unTaggedString[j])
-
pat = pat.toArray
-
parent = parsed_sentence.getParents(pat[0]).toArray
-
end
-
#puts "parent of #{unTaggedString[j]} is #{parent[0]}"
-
if(!parent.nil? and !parent[0].nil?)
-
parents[j] = (parent[0].to_s)[0..(parent[0].to_s).index("-")-1]#extracting the name of the parent (since it is in the foramt-> "name-POS")
-
#puts "parents[#{j}] = #{parents[j]}"
-
else
-
parents[j] = nil
-
end
-
end
-
return parents
-
end #end of find_parents method
-
#------------------------------------------#------------------------------------------#------------------------------------------
-
#Identifying parents and labels for the vertices
-
1
def find_labels(t)
-
# puts "Inside find_labels"
-
unTaggedString = t.split(" ")
-
t = StanfordCoreNLP::Text.new(t)
-
@pipeline.annotate(t)
-
#for each sentence identify theparsed form of the sentence
-
sentence = t.get(:sentences).toArray
-
parsed_sentence = sentence[0].get(:collapsed_c_c_processed_dependencies)
-
labels = Array.new
-
labelCounter = 0
-
govDep = parsed_sentence.typedDependencies.toArray
-
#for each untagged token
-
for j in (0..unTaggedString.length - 1)
-
unTaggedString[j].gsub!(".", "")
-
unTaggedString[j].gsub!(",", "")
-
#puts "Label for #{unTaggedString[j]}"
-
#identify its corresponding position in govDep and fetch its label
-
for k in (0..govDep.length - 1)
-
#puts "Comparing with #{govDep[k].dep.value()}"
-
if(govDep[k].dep.value() == unTaggedString[j])
-
labels[j] = govDep[k].reln.getShortName()
-
#puts labels[j]
-
labelCounter+=1
-
break
-
end
-
end
-
end
-
return labels
-
end # end of find_labels method
-
#------------------------------------------#------------------------------------------#------------------------------------------
-
=begin
-
* Setting semantic labels for edges based on the labels vertices have with their parents
-
=end
-
1
def set_semantic_labels_for_edges
-
# puts "*** inside set_semantic_labels_for_edges"
-
for i in (0.. @vertices.length - 1)
-
if(!@vertices[i].nil? and !@vertices[i].parent.nil?) #parent = null for ROOT
-
#search for the parent vertex
-
for j in (0..@vertices.length - 1)
-
if(!@vertices[j].nil? and (@vertices[j].name.casecmp(@vertices[i].parent) == 0 or
-
@vertices[j].name.downcase.include?(@vertices[i].parent.downcase)))
-
# puts("**Parent:: #{@vertices[j].name}")
-
parent = @vertices[j]
-
break #break out of search for the parent
-
end
-
end
-
if(!parent.nil?)#{
-
#check if an edge exists between vertices[i] and the parent
-
for k in (0..@edges.length - 1)
-
if(!@edges[k].nil? and !@edges[k].in_vertex.nil? and !@edges[k].out_vertex.nil?)
-
if((@edges[k].in_vertex.name.equal?(@vertices[i].name) and @edges[k].out_vertex.name.equal?(parent.name)) or (@edges[k].in_vertex.name.equal?(parent.name) and @edges[k].out_vertex.name.equal?(@vertices[i].name)))
-
#set the role label
-
if(@edges[k].label.nil?)
-
@edges[k].label = @vertices[i].label
-
elsif(!@edges[k].label.nil? and (@edges[k].label == "NMOD" or @edges[k].label == "PMOD") and (@vertices[i].label != "NMOD" or @vertices[i].label != "PMOD"))
-
@edges[k].label = @vertices[i].label
-
end
-
end
-
end
-
end
-
end#end of if paren.nil? condition
-
end
-
end #end of for loop
-
end #end of set_semantic_labels_for_edges method
-
-
end # end of the class GraphGenerator
-
#------------------------------------------#------------------------------------------#------------------------------------------
-
=begin
-
Identifying frequency of edges and pruning out edges that do no meet the threshold conditions
-
=end
-
1
def identify_frequency_and_prune_edges(edges, num)
-
# puts "inside frequency threshold! :: num #{num}"
-
#freqEdges maintains the top frequency edges from ALPHA_FREQ to BETA_FREQ
-
freqEdges = Array.new #from alpha = 3 to beta = 10
-
#iterating through all the edges
-
for j in (0..num-1)
-
if(!edges[j].nil?)
-
if(edges[j].frequency <= BETA_FREQ and edges[j].frequency >= ALPHA_FREQ and !freqEdges[edges[j].frequency-1].nil?)#{
-
for i in (0..freqEdges[edges[j].frequency-1].length - 1)#iterating to find i for which freqEdges is null
-
if(!freqEdges[edges[j].frequency-1][i].nil?)
-
break
-
end
-
end
-
freqEdges[edges[j].frequency-1][i] = edges[j]
-
end
-
end
-
end
-
selectedEdges = Array.new
-
#Selecting only those edges that satisfy the frequency condition [between ALPHA and BETA]
-
j = BETA_FREQ-1
-
while j >= ALPHA_FREQ-1 do
-
if(!freqEdges[j].nil?)
-
for i in (0..num-1)
-
if(!freqEdges[j][i].nil?)
-
selectedEdges[maxSelected] = freqEdges[j][i]
-
maxSelected+=1
-
end
-
end
-
end
-
j-=1
-
end
-
-
if(maxSelected != 0)
-
@num_edges = maxSelected #replacing numEdges with the number of selected edges
-
end
-
return selectedEdges
-
end
-
#------------------------------------------#------------------------------------------#------------------------------------------
-
=begin
-
If negative words were found and a neg. descriptor is seen => (-)(-) = (+)
-
public static String[] NEGATIVE_DESCRIPTORS = new String[4879];
-
=end
-
1
NEGATIVE_DESCRIPTORS = [
-
#negated phrases (topical words I spotted in text)
-
"NOTHING", "nowhere", "scarcely", "scarce", "zero", "drawback",
-
"barely", "hardly", "deny", "refuse", "fail", "failed",
-
"without", "ambiguous", "ambiguity", "neither", "empty",
-
"deviation", "lacks", "lack", "lacking", "lacked", "abrupt", "abruptly", "somewhat", "copied", "copy",
-
"overbalanced", "ambiguous", "missing", "poor",
-
"negative", "negatively", "underrepresented", "duplication", "wrong", "mistake", "mistakes","duplications",
-
"duplicate", "duplicated", "duplicating", "avoids", "messy", "deleted", "cumbersome", "strange",
-
"strangely", "misspell", "misspelling", "misspellings", "misspelt", "verbose", "confuse", "confusion", "confusing",
-
"confused", "confuses", "trivial", "triviality", "typo", "typos", "somewhat", "concerns", "concern",
-
"barring", "overuse", "repitition", "useless", "biased", "rushed", "absent", "wordy", "bad", "less",
-
"unclear", "difficult", "vague", "briefly", "hard", "broken","replicate","replicated", "digress", "clutter",
-
"cluttered", "inadequate", "deviation", "contrived", "contrive", "horrid", "trouble","uneven", "unevenly", "alot",
-
"incorrect"]
-
=begin
-
SENTENCE CLAUSE OR PHRASE FOLLOWING THESE WORDS CARRY A NEGATIVE MEANING (EITHER SUBTLE OR OVERT)
-
=end
-
1
NEGATED_WORDS = ["not", "n't", "WON'T", "DON'T", "DIDN'T",
-
"DOESN'T", "WOULDN'T", "COULDN'T", "SHOULDN'T", "WASN'T",
-
"WEREN'T", "AREN'T", "ISN'T", "HAVEN'T", "HASN'T", "HADN'T", "NOBODY",
-
"CAN'T","SHALLN'T", "MUSTN'T", "AIN'T", "cannot",
-
#without the apostrophe
-
"cant", "dont", "wont","isnt","hasnt", "hadnt", "havent","arent", "werent", "wouldnt",
-
"didnt", "couldnt", "shouldnt", "mustnt", "shallnt",
-
#other words that indicate negations (negative quantifiers)
-
"NO", "NEVER", "NONE"]
-
-
1
NEGATIVE_PHRASES = ["too concise",
-
"taken from", "been removed", "too long", "off topic",
-
"too short", "run on", "too much", "been directly", "similar to",
-
"at odds", "grammatical errors", "grammatical error", "available online",
-
"make up", "made up", "crammed up"]
-
-
1
SUGGESTIVE_WORDS = ["would", "could", "should",
-
"maybe", "perhaps", "might", "suggest", "suggests", "suggested", "advise", "advice","could've", "would've",
-
"should've", "might've", "may", #"will", "better", "can"
-
#when they provide sample examples
-
"eg",
-
#typos or colloqial
-
"I'd", "We'd", "they'd", "you'd"]
-
-
#suggestive phrases
-
1
SUGGESTIVE_PHRASES = ["for example","try adding", "instead of", #(explaining what isnt good and what potentially could be)
-
"little more", "try to", "need more", "needs to", "need to", "more detail",
-
"can be", "was expecting", "am expecting", "is required"]
-
-
1
require 'automated_metareview/text_preprocessing'
-
1
require 'automated_metareview/constants'
-
1
require 'automated_metareview/graph_generator'
-
1
require 'ruby-web-search'
-
-
1
class PlagiarismChecker
-
=begin
-
reviewText and submText are array containing review and submission texts
-
=end
-
1
def check_for_plagiarism(review_text, subm_text)
-
result = false
-
for l in 0..review_text.length - 1 #iterating through the review's sentences
-
review = review_text[l].to_s
-
# puts "review.class #{review.to_s.class}.. review - #{review}"
-
for m in 0..subm_text.length - 1 #iterating though the submission's sentences
-
submission = subm_text[m].to_s
-
# puts "submission.class #{submission.to_s.class}..submission - #{submission}"
-
rev_len = 0
-
-
rev = review.split(" ") #review's tokens, taking 'n' at a time
-
array = review.split(" ")
-
-
while(rev_len < array.length) do
-
if(array[rev_len] == " ") #skipping empty
-
rev_len+=1
-
next
-
end
-
-
#generating the sentence segment you'd like to compare
-
rev_phrase = array[rev_len]
-
add = 0 #add on to this when empty strings found
-
for j in rev_len+1..(NGRAM+rev_len+add-1) #concatenating 'n' tokens
-
if(j < array.length)
-
if(array[j] == "") #skipping empty
-
add+=1
-
next
-
end
-
rev_phrase = rev_phrase +" "+ array[j]
-
end
-
end
-
-
if(j == array.length)
-
#if j has reached the end of the array, then reset rev_len to the end of array to, or shorter strings will be compared
-
rev_len = array.length
-
end
-
-
#replacing punctuation
-
tp = TextPreprocessing.new
-
submission = tp.contains_punct(submission)
-
rev_phrase = tp.contains_punct(rev_phrase)
-
#puts "Review phrase: #{rev_phrase} .. #{rev_phrase.split(" ").length}"
-
-
#checking if submission contains the review and that only NGRAM number of review tokens are compared
-
if(rev_phrase.split(" ").length == NGRAM and submission.downcase.include?(rev_phrase.downcase))
-
result = true
-
break
-
end
-
#System.out.println("^^^ Plagiarism result:: "+result);
-
rev_len+=1
-
end #end of the while loop
-
if(result == true)
-
break
-
end
-
end #end of for loop for submission
-
if(result == true)
-
break
-
end
-
end #end of for loop for reviews
-
return result
-
end
-
#-------------------------
-
-
=begin
-
Checking if the response has been copied from the review questions or from other responses submitted.
-
=end
-
1
def compare_reviews_with_questions_responses(auto_metareview, map_id)
-
review_text_arr = auto_metareview.review_array
-
response = Response.find(:first, :conditions => ["map_id = ?", map_id])
-
scores = Score.find(:all, :conditions => ["response_id = ?", response.id])
-
questions = Array.new
-
#fetching the questions for the responses
-
for i in 0..scores.length - 1
-
questions << Question.find_by_sql(["Select * from questions where id = ?", scores[i].question_id])[0].txt
-
end
-
-
count_copies = 0 #count of the number of responses that are copies either of questions of other responses
-
rev_array = Array.new #holds the non-plagiairised responses
-
#comparing questions with text
-
for i in 0..scores.length - 1
-
if(!questions[i].nil? and !review_text_arr[i].nil? and questions[i].downcase == review_text_arr[i].downcase)
-
count_copies+=1
-
next #skip comparing with other responses
-
end
-
-
#comparing response with other responses
-
flag = 0
-
for j in 0..review_text_arr.length - 1
-
if(i != j and !review_text_arr[i].nil? and !review_text_arr[j].nil? and review_text_arr[i].downcase == review_text_arr[j].downcase)
-
count_copies+=1
-
flag = 1
-
break
-
end
-
end
-
-
if(flag == 0) #ensuring no match with any of the review array's responses
-
rev_array << review_text_arr[i]
-
end
-
end
-
-
#setting @review_array as rev_array
-
if(count_copies > 0) #resetting review_array only when plagiarism was found
-
auto_metareview.review_array = rev_array
-
end
-
-
if(count_copies > 0 and count_copies == scores.length)
-
return ALL_RESPONSES_PLAGIARISED #plagiarism, with all other metrics 0
-
elsif(count_copies > 0)
-
return SOME_RESPONSES_PLAGIARISED #plagiarism, while evaluating other metrics
-
end
-
end
-
-
=begin
-
Checking if the response was copied from google
-
=end
-
1
def google_search_response(auto_metareview)
-
review_text_arr = auto_metareview.review_array
-
# require 'ruby-web-search'
-
count = 0
-
temp_array = Array.new
-
review_text_arr.each{
-
|rev_text|
-
if(!rev_text.nil?)
-
#placing the search text within quotes to search exact match for the complete text
-
response = RubyWebSearch::Google.search(:query => "\""+ rev_text +"\"")
-
#if the results are greater than 0, then the text has been copied
-
if(response.results.length > 0)
-
count+=1
-
else
-
temp_array << rev_text #copying the non-plagiarised text for evaluation
-
end
-
end
-
}
-
#setting temp_array as the @review_array
-
auto_metareview.review_array = temp_array
-
-
if(count > 0)
-
return true
-
else
-
return false
-
end
-
end
-
-
end
-
-
-
1
require 'automated_metareview/wordnet_based_similarity'
-
1
require 'automated_metareview/constants'
-
-
1
class PredictClass
-
=begin
-
Identifies the probabilities of a review belonging to each of the three classes.
-
Returns an array of probablities (length = numClasses)
-
=end
-
#predicting the review's class
-
1
def predict_classes(pos_tagger, core_NLP_tagger, review_text, review_graph, pattern_files_array, num_classes)
-
#reading the patterns from the pattern files
-
patterns_files = Array.new
-
pattern_files_array.each do |file|
-
patterns_files << file #collecting the file names for each class of patterns
-
end
-
-
tc = TextPreprocessing.new
-
single_patterns = Array.new(num_classes){Array.new}
-
#reading the patterns from each of the pattern files
-
for i in (0..num_classes - 1) #for every class
-
#read_patterns in TextPreprocessing helps read patterns in the format 'X = Y'
-
single_patterns[i] = tc.read_patterns(patterns_files[i], pos_tagger)
-
end
-
-
#Predicting the probability of the review belonging to each of the content classes
-
wordnet = WordnetBasedSimilarity.new
-
max_probability = 0.0
-
class_value = 0
-
edges = review_graph.edges
-
class_prob = Array.new #contains the probabilities for each of the classes - it contains 3 rows for the 3 classes
-
#comparing each test review text with patterns from each of the classes
-
for k in (0..num_classes - 1)
-
#comparing edges with patterns from a particular class
-
class_prob[k] = compare_review_with_patterns(edges, single_patterns[k], wordnet)/6.to_f #normalizing the result
-
#we divide the match by 6 to ensure the value is in the range of [0-1]
-
end #end of for loop for the classes
-
-
#printing the probability values
-
# puts("########## Probability for test review:: "+review_text[0]+" is::")
-
# for k in (0..num_classes - 1)
-
# puts "class_prob[#{k}] .. #{class_prob[k]}"
-
# end
-
return class_prob
-
end #end of the prediction method
-
#------------------------------------------#------------------------------------------#------------------------------------------
-
-
1
def compare_review_with_patterns(single_edges, single_patterns, wordnet)
-
final_class_sum = 0.0
-
final_edge_num = 0
-
single_edge_matches = Array.new(single_edges.length){Array.new}
-
#resetting the average_match values for all the edges, before matching with the single_patterns for a new class
-
for i in 0..single_edges.length - 1
-
if(!single_edges[i].nil?)
-
single_edges[i].average_match = 0
-
end
-
end
-
-
#comparing each single edge with all the patterns
-
for i in (0..single_edges.length - 1) #iterating through the single edges
-
max_match = 0
-
if(!single_edges[i].nil?)
-
for j in (0..single_patterns.length - 1)
-
if(!single_patterns[j].nil?)
-
single_edge_matches[i][j] = compare_edges(single_edges[i], single_patterns[j], wordnet)
-
if(single_edge_matches[i][j] > max_match)
-
max_match = single_edge_matches[i][j]
-
end
-
end
-
end #end of for loop for the patterns
-
single_edges[i].average_match = max_match
-
-
#calculating class average
-
if(single_edges[i].average_match != 0.0)
-
final_class_sum = final_class_sum + single_edges[i].average_match
-
final_edge_num+=1
-
end
-
end #end of the if condition
-
end #end of for loop
-
-
if(final_edge_num == 0)
-
final_edge_num = 1
-
end
-
-
# puts("final_class_sum:: #{final_class_sum} final_edge_num:: #{final_edge_num} Class average #{final_class_sum/final_edge_num}")
-
return final_class_sum/final_edge_num #maxMatch
-
end #end of determineClass method
-
#------------------------------------------#------------------------------------------#------------------------------------------
-
-
1
def compare_edges(e1, e2, wordnet)
-
speller = Aspell.new("en_US")
-
speller.suggestion_mode = Aspell::NORMAL
-
-
avg_match_without_syntax = 0
-
#compare edges so that only non-nouns or non-subjects are compared
-
# if(!e1.in_vertex.pos_tag.include?("NN") and !e1.out_vertex.pos_tag.include?("NN"))
-
avg_match_without_syntax = (wordnet.compare_strings(e1.in_vertex, e2.in_vertex, speller) +
-
wordnet.compare_strings(e1.out_vertex, e2.out_vertex, speller))/2.to_f
-
# elsif(!e1.in_vertex.pos_tag.include?("NN"))
-
# avg_match_without_syntax = wordnet.compare_strings(e1.in_vertex, e2.in_vertex, speller)
-
# elsif(!e1.out_vertex.pos_tag.include?("NN"))
-
# avg_match_without_syntax = wordnet.compare_strings(e1.out_vertex, e2.out_vertex, speller)
-
# end
-
-
avg_match_with_syntax = 0
-
#matching in-out and out-in vertices
-
# if(!e1.in_vertex.pos_tag.include?("NN") and !e1.out_vertex.pos_tag.include?("NN"))
-
avg_match_with_syntax = (wordnet.compare_strings(e1.in_vertex, e2.out_vertex, speller) +
-
wordnet.compare_strings(e1.out_vertex, e2.in_vertex, speller))/2.to_f
-
# elsif(!e1.in_vertex.pos_tag.include?("NN"))
-
# avg_match_with_syntax = wordnet.compare_strings(e1.in_vertex, e2.out_vertex, speller)
-
# elsif(!e1.out_vertex.pos_tag.include?("NN"))
-
# avg_match_with_syntax = wordnet.compare_strings(e1.out_vertex, e2.in_vertex, speller)
-
# end
-
-
if(avg_match_without_syntax > avg_match_with_syntax)
-
return avg_match_without_syntax
-
else
-
return avg_match_with_syntax
-
end
-
end #end of the compare_edges method
-
end
-
1
require 'automated_metareview/negations'
-
1
require 'automated_metareview/constants'
-
-
1
class SentenceState
-
1
attr_accessor :broken_sentences
-
1
def identify_sentence_state(str_with_pos_tags)
-
# puts("**** Inside identify_sentence_state #{str_with_pos_tags}")
-
#break the sentence at the co-ordinating conjunction
-
num_conjunctions = break_at_coordinating_conjunctions(str_with_pos_tags)
-
-
states_array = Array.new
-
if(@broken_sentences == nil)
-
states_array[0] = sentence_state(str_with_pos_tags)
-
#identifying states for each of the sentence segments
-
else
-
for i in (0..num_conjunctions)
-
if(!@broken_sentences[i].nil?)
-
states_array[i] = sentence_state(@broken_sentences[i])
-
end
-
end
-
end
-
return states_array
-
end #end of the methods
-
#------------------------------------------#------------------------------------------
-
1
def break_at_coordinating_conjunctions(str_with_pos_tags)
-
st = str_with_pos_tags.split(" ")
-
count = st.length
-
counter = 0
-
-
@broken_sentences = Array.new
-
#if the sentence contains a co-ordinating conjunction
-
if(str_with_pos_tags.include?("CC"))
-
counter = 0
-
temp = ""
-
for i in (0..count-1)
-
ps = st[i]
-
if(!ps.nil? and ps.include?("CC"))
-
@broken_sentences[counter] = temp #for "run/NN on/IN..."
-
counter+=1
-
temp = ps[0..ps.index("/")]
-
#the CC or IN goes as part of the following sentence
-
elsif (!ps.nil? and !ps.include?("CC"))
-
temp = temp +" "+ ps[0..ps.index("/")]
-
end
-
end
-
if(!temp.empty?) #setting the last sentence segment
-
@broken_sentences[counter] = temp
-
counter+=1
-
end
-
else
-
@broken_sentences[counter] = str_with_pos_tags
-
counter+=1
-
end
-
return counter
-
end #end of the method
-
#------------------------------------------#------------------------------------------
-
-
#Checking if the token is a negative token
-
1
def sentence_state(str_with_pos_tags)
-
state = POSITIVE
-
#checking single tokens for negated words
-
st = str_with_pos_tags.split(" ")
-
count = st.length
-
tokens = Array.new
-
tagged_tokens = Array.new
-
i = 0
-
interim_noun_verb = false #0 indicates no interim nouns or verbs
-
-
#fetching all the tokens
-
for k in (0..st.length-1)
-
ps = st[k]
-
#setting the tagged string
-
tagged_tokens[i] = ps
-
if(ps.include?("/"))
-
ps = ps[0..ps.index("/")-1]
-
end
-
#removing punctuations
-
if(ps.include?("."))
-
tokens[i] = ps[0..ps.index(".")-1]
-
elsif(ps.include?(","))
-
tokens[i] = ps.gsub(",", "")
-
elsif(ps.include?("!"))
-
tokens[i] = ps.gsub("!", "")
-
elsif(ps.include?(";"))
-
tokens[i] = ps.gsub(";", "")
-
else
-
tokens[i] = ps
-
i+=1
-
end
-
end#end of the for loop
-
-
#iterating through the tokens to determine state
-
prev_negative_word =""
-
for j in (0..i-1)
-
#checking type of the word
-
#checking for negated words
-
if(is_negative_word(tokens[j]) == NEGATED)
-
returned_type = NEGATIVE_WORD
-
#checking for a negative descriptor (indirect indicators of negation)
-
elsif(is_negative_descriptor(tokens[j]) == NEGATED)
-
returned_type = NEGATIVE_DESCRIPTOR
-
#2-gram phrases of negative phrases
-
elsif(j+1 < count && !tokens[j].nil? && !tokens[j+1].nil? &&
-
is_negative_phrase(tokens[j]+" "+tokens[j+1]) == NEGATED)
-
returned_type = NEGATIVE_PHRASE
-
j = j+1
-
#if suggestion word is found
-
elsif(is_suggestive(tokens[j]) == SUGGESTIVE)
-
returned_type = SUGGESTIVE
-
#2-gram phrases suggestion phrases
-
elsif(j+1 < count && !tokens[j].nil? && !tokens[j+1].nil? &&
-
is_suggestive_phrase(tokens[j]+" "+tokens[j+1]) == SUGGESTIVE)
-
returned_type = SUGGESTIVE
-
j = j+1
-
#else set to positive
-
else
-
returned_type = POSITIVE
-
end
-
-
#----------------------------------------------------------------------
-
#comparing 'returnedType' with the existing STATE of the sentence clause
-
#after returnedType is identified, check its state and compare it to the existing state
-
#if present state is negative and an interim non-negative or non-suggestive word was found, set the flag to true
-
if((state == NEGATIVE_WORD or state == NEGATIVE_DESCRIPTOR or state == NEGATIVE_PHRASE) and returned_type == POSITIVE)
-
if(interim_noun_verb == false and (tagged_tokens[j].include?("NN") or tagged_tokens[j].include?("PR") or tagged_tokens[j].include?("VB") or tagged_tokens[j].include?("MD")))
-
interim_noun_verb = true
-
end
-
end
-
-
if(state == POSITIVE and returned_type != POSITIVE)
-
state = returned_type
-
#when state is a negative word
-
elsif(state == NEGATIVE_WORD) #previous state
-
if(returned_type == NEGATIVE_WORD)
-
#these words embellish the negation, so only if the previous word was not one of them you make it positive
-
if(prev_negative_word.casecmp("NO") != 0 and prev_negative_word.casecmp("NEVER") != 0 and prev_negative_word.casecmp("NONE") != 0)
-
state = POSITIVE #e.g: "not had no work..", "doesn't have no work..", "its not that it doesn't bother me..."
-
else
-
state = NEGATIVE_WORD #e.g: "no it doesn't help", "no there is no use for ..."
-
end
-
interim_noun_verb = false #resetting
-
elsif(returned_type == NEGATIVE_DESCRIPTOR or returned_type == NEGATIVE_PHRASE)
-
state = POSITIVE #e.g.: "not bad", "not taken from", "I don't want nothing", "no code duplication"// ["It couldn't be more confusing.."- anomaly we dont handle this for now!]
-
interim_noun_verb = false #resetting
-
elsif(returned_type == SUGGESTIVE)
-
#e.g. " it is not too useful as people could...", what about this one?
-
if(interim_noun_verb == true) #there are some words in between
-
state = NEGATIVE_WORD
-
else
-
state = SUGGESTIVE #e.g.:"I do not(-) suggest(S) ..."
-
end
-
interim_noun_verb = false #resetting
-
end
-
#when state is a negative descriptor
-
elsif(state == NEGATIVE_DESCRIPTOR)
-
if(returned_type == NEGATIVE_WORD)
-
if(interim_noun_verb == true)#there are some words in between
-
state = NEGATIVE_WORD #e.g: "hard(-) to understand none(-) of the comments"
-
else
-
state = POSITIVE #e.g."He hardly not...."
-
end
-
interim_noun_verb = false #resetting
-
elsif(returned_type == NEGATIVE_DESCRIPTOR)
-
if(interim_noun_verb == true)#there are some words in between
-
state = NEGATIVE_DESCRIPTOR #e.g:"there is barely any code duplication"
-
else
-
state = POSITIVE #e.g."It is hardly confusing..", but what about "it is a little confusing.."
-
end
-
interim_noun_verb = false #resetting
-
elsif(returned_type == NEGATIVE_PHRASE)
-
if(interim_noun_verb == true)#there are some words in between
-
state = NEGATIVE_PHRASE #e.g:"there is barely any code duplication"
-
else
-
state = POSITIVE #e.g.:"it is hard and appears to be taken from"
-
end
-
interim_noun_verb = false #resetting
-
elsif(returned_type == SUGGESTIVE)
-
state = SUGGESTIVE #e.g.:"I hardly(-) suggested(S) ..."
-
interim_noun_verb = false #resetting
-
end
-
#when state is a negative phrase
-
elsif(state == NEGATIVE_PHRASE)
-
if(returned_type == NEGATIVE_WORD)
-
if(interim_noun_verb == true)#there are some words in between
-
state = NEGATIVE_WORD #e.g."It is too short the text and doesn't"
-
else
-
state = POSITIVE #e.g."It is too short not to contain.."
-
end
-
interim_noun_verb = false #resetting
-
elsif(returned_type == NEGATIVE_DESCRIPTOR)
-
state = NEGATIVE_DESCRIPTOR #e.g."It is too short barely covering..."
-
interim_noun_verb = false #resetting
-
elsif(returned_type == NEGATIVE_PHRASE)
-
state = NEGATIVE_PHRASE #e.g.:"it is too short, taken from ..."
-
interim_noun_verb = false #resetting
-
elsif(returned_type == SUGGESTIVE)
-
state = SUGGESTIVE #e.g.:"I too short and I suggest ..."
-
interim_noun_verb = false #resetting
-
end
-
#when state is suggestive
-
elsif(state == SUGGESTIVE) #e.g.:"I might(S) not(-) suggest(S) ..."
-
if(returned_type == NEGATIVE_DESCRIPTOR)
-
state = NEGATIVE_DESCRIPTOR
-
elsif(returned_type == NEGATIVE_PHRASE)
-
state = NEGATIVE_PHRASE
-
end
-
#e.g.:"I suggest you don't.." -> suggestive
-
interim_noun_verb = false #resetting
-
end
-
-
#setting the prevNegativeWord
-
if(tokens[j].casecmp("NO") == 0 or tokens[j].casecmp("NEVER") == 0 or tokens[j].casecmp("NONE") == 0)
-
prev_negative_word = tokens[j]
-
end
-
-
end #end of for loop
-
-
if(state == NEGATIVE_DESCRIPTOR or state == NEGATIVE_WORD or state == NEGATIVE_PHRASE)
-
state = NEGATED
-
end
-
-
return state
-
end
-
-
#------------------------------------------#------------------------------------------
-
-
#Checking if the token is a negative token
-
1
def is_negative_word(word)
-
not_negated = POSITIVE
-
for i in (0..NEGATED_WORDS.length - 1)
-
if(word.casecmp(NEGATED_WORDS[i]) == 0)
-
not_negated = NEGATED #indicates negation found
-
break
-
end
-
end
-
return not_negated
-
end
-
#------------------------------------------#------------------------------------------
-
-
#Checking if the token is a negative token
-
1
def is_negative_descriptor(word)
-
not_negated = POSITIVE
-
for i in (0..NEGATIVE_DESCRIPTORS.length - 1)
-
if(word.casecmp(NEGATIVE_DESCRIPTORS[i]) == 0)
-
not_negated = NEGATED #indicates negation found
-
break
-
end
-
end
-
return not_negated
-
end
-
-
#------------------------------------------#------------------------------------------
-
-
#Checking if the phrase is negative
-
1
def is_negative_phrase(phrase)
-
not_negated = POSITIVE
-
for i in (0..NEGATIVE_PHRASES.length - 1)
-
if(phrase.casecmp(NEGATIVE_PHRASES[i]) == 0)
-
not_negated = NEGATED #indicates negation found
-
break
-
end
-
end
-
return not_negated
-
end
-
-
#------------------------------------------#------------------------------------------
-
#Checking if the token is a suggestive token
-
1
def is_suggestive(word)
-
not_suggestive = POSITIVE
-
#puts "inside is_suggestive for token:: #{word}"
-
for i in (0..SUGGESTIVE_WORDS.length - 1)
-
if(word.casecmp(SUGGESTIVE_WORDS[i]) == 0)
-
not_suggestive = SUGGESTIVE #indicates negation found
-
break
-
end
-
end
-
return not_suggestive
-
end
-
#------------------------------------------#------------------------------------------
-
-
#Checking if the PHRASE is suggestive
-
1
def is_suggestive_phrase(phrase)
-
not_suggestive = POSITIVE
-
for i in (0..SUGGESTIVE_PHRASES.length - 1)
-
if(phrase.casecmp(SUGGESTIVE_PHRASES[i]) == 0)
-
not_suggestive = SUGGESTIVE #indicates negation found
-
break
-
end
-
end
-
return not_suggestive
-
end
-
-
end #end of the class
-
1
require 'automated_metareview/constants'
-
1
require 'automated_metareview/edge'
-
1
require 'automated_metareview/vertex'
-
-
1
class TextPreprocessing
-
-
=begin
-
Fetching review data from the tables based on the response_map id
-
=end
-
1
def fetch_review_data(auto_metareview, map_id)
-
reviews = Array.new
-
responses = Response.find(:first, :conditions => ["map_id = ?", map_id], :order => "updated_at DESC")
-
auto_metareview.responses = responses
-
auto_metareview.response_id = responses.id
-
# puts "auto_metareview.response_id #{auto_metareview.response_id}"
-
# puts "responses updated_at #{responses.updated_at}"
-
responses.scores.each{
-
| review_score |
-
if(review_score.comments != nil and !review_score.comments.rstrip.empty?)
-
# puts review_score.comments
-
reviews << review_score.comments
-
end
-
}
-
return reviews
-
end
-
#------------------------------------------#------------------------------------------#------------------------------------------
-
=begin
-
Fetching submission data from the url submitted by the reviewee
-
=end
-
1
def fetch_submission_data(map_id)
-
subm_array = Array.new
-
response_map = ResponseMap.find(:first, :conditions => ["id = ?", map_id])
-
reviewee_id = response_map.reviewee_id
-
reviewed_object = response_map.reviewed_object_id
-
url = Participant.find(:first, :conditions => ["id = ?", reviewee_id]).submitted_hyperlinks
-
if(url.nil?)#in case of team assignments
-
teams_users = TeamsUser.find(:all, :conditions => ["team_id = ?", reviewee_id])
-
teams_users.each{
-
|team_user|
-
url = Participant.find(:first, :conditions => ["user_id = ? and parent_id = ?", team_user.user_id, reviewed_object]).submitted_hyperlinks
-
if(!url.nil?)#break out when you find the url
-
break
-
end
-
}
-
end
-
# puts "***url #{url} #{url}"
-
#fetching the url submitted by the reviewee
-
url = url[url.rindex("http")..url.length-2] #use "rindex" to fetch last occurrence of the substring - useful if there are multiple urls
-
# puts "***url #{url} #{url.class}"
-
page = Nokogiri::HTML(open(url))
-
#fetching the paragraph texts from the specified url
-
if(page.css('p').count != 0)
-
page.css('p').each do |subm|
-
# puts "subm.text.. #{subm.text}"
-
subm_array << subm.text
-
end
-
end
-
#for google docs where the text is placed inside <script></script> tags
-
if(page.css('script').count != 0)
-
page.css('script').each do |subm|
-
if(!subm.children[0].to_s.index("\"s\":\"").nil? and !subm.children[0].to_s.index("\\n\"},").nil?) #the string indicates the beginning of the text in the script
-
subm_array << subm.children[0].to_s[subm.children[0].to_s.index("\"s\":\"")+5, subm.children[0].to_s.index("\\n\"},")]
-
end
-
end
-
end
-
return subm_array
-
end
-
#------------------------------------------#------------------------------------------#------------------------------------------
-
=begin
-
pre-processes the review text and sends it in for graph formation and further analysis
-
=end
-
1
def segment_text(flag, text_array)
-
if(flag == 0)
-
reviews = Array.new(1){Array.new}
-
else
-
reviews = Array.new(50){Array.new} #50 is the number of different reviews/submissions
-
end
-
-
i = 0
-
j = 0
-
-
for k in (0..text_array.length-1)
-
text = text_array[k]
-
if(flag == 1) #reset i (the sentence counter) to 0 for test reviews
-
reviews[j] = Array.new #initializing the array for sentences in a test review
-
i = 0
-
end
-
-
#******* Pre-processing the review/submission text **********
-
#replacing commas in large numbers, makes parsing sentences with commas confusing!
-
#replacing quotation marks
-
text.gsub!("\"", "")
-
text.gsub!("(", "")
-
text.gsub!(")", "")
-
if(text.include?("http://"))
-
text = remove_urls(text)
-
end
-
#break the text into multiple sentences
-
beginn = 0
-
if(text.include?(".") or text.include?("?") or text.include?("!") or text.include?(",") or text.include?(";") ) #new clause or sentence
-
while(text.include?(".") or text.include?("?") or text.include?("!") or text.include?(",") or text.include?(";")) do #the text contains more than 1 sentence
-
endd = 0
-
#these 'if' conditions have to be independent, cause the value of 'endd' could change for the different types of punctuations
-
if(text.include?("."))
-
endd = text.index(".")
-
end
-
if((text.include?("?") and endd != 0 and endd > text.index("?")) or (text.include?("?") and endd == 0))#if a ? occurs before a .
-
endd = text.index("?")
-
end
-
if((text.include?("!") and endd!= 0 and endd > text.index("!")) or (text.include?("!") and endd ==0))#if an ! occurs before a . or a ?
-
endd = text.index("!")
-
end
-
if((text.include?(",") and endd != 0 and endd > text.index(",")) or (text.include?(",") and endd == 0)) #if a , occurs before any of . or ? or !
-
endd = text.index(",")
-
end
-
if((text.include?(";") and endd != 0 and endd > text.index(";")) or (text.include?(";") and endd == 0)) #if a ; occurs before any of . or ?, ! or ,
-
endd = text.index(";")
-
end
-
-
#check if the string between two commas or punctuations is there to buy time e.g. ", say," ",however," ", for instance, "...
-
if(flag == 0) #training
-
reviews[0][i] = text[beginn..endd].strip
-
else #testing
-
reviews[j][i] = text[beginn..endd].strip
-
end
-
i+=1 #incrementing the sentence counter
-
text = text[(endd+1)..text.length] #from end+1 to the end of the string variable
-
end #end of the while loop
-
else #if there is only 1 sentence in the text
-
if(flag == 0)#training
-
reviews[0][i] = text.strip
-
i+=1 #incrementing the sentence counter
-
else #testing
-
reviews[j][i] = text.strip
-
end
-
end
-
-
if(flag == 1)#incrementing reviews counter only for test reviews
-
j+=1
-
end
-
end #end of the for loop with 'k' reading text rows
-
-
#setting the number of reviews before returning
-
if(flag == 0)#training
-
num_reviews = 1 #for training the number of reviews is 1
-
else #testing
-
num_reviews = j
-
end
-
-
if(flag == 0)
-
return reviews[0]
-
end
-
end
-
#------------------------------------------#------------------------------------------#------------------------------------------
-
=begin
-
* Reads the patterns from the csv file containing them.
-
* maxValue is the maximum value of the patterns found
-
=end
-
-
1
def read_patterns(filename, pos)
-
num = 1000 #some large number
-
patterns = Array.new
-
state = POSITIVE
-
i = 0 #keeps track of the number of edges
-
-
#setting the state for problem detection and suggestive patterns
-
if(filename.include?("prob"))
-
state = NEGATED
-
elsif(filename.include?("suggest"))
-
state = SUGGESTIVE
-
end
-
-
FasterCSV.foreach(filename) do |text|
-
in_vertex = text[0][0..text[0].index("=")-1].strip
-
out_vertex = text[0][text[0].index("=")+2..text[0].length].strip
-
-
first_string_in_vertex = pos.get_readable(in_vertex.split(" ")[0]) #getting the first token in vertex to determine POS
-
first_string_out_vertex = pos.get_readable(out_vertex.split(" ")[0]) #getting the first token in vertex to determine POS
-
-
patterns[i] = Edge.new("noun", NOUN)
-
#setting the invertex
-
if(first_string_in_vertex.include?("/NN") or first_string_in_vertex.include?("/PRP") or first_string_in_vertex.include?("/IN") or first_string_in_vertex.include?("/EX") or first_string_in_vertex.include?("/WP"))
-
patterns[i].in_vertex = Vertex.new(in_vertex, NOUN, i, state, nil, nil, first_string_in_vertex[first_string_in_vertex.index("/")+1..first_string_in_vertex.length])
-
elsif(first_string_in_vertex.include?("/VB") or first_string_in_vertex.include?("MD"))
-
patterns[i].in_vertex = Vertex.new(in_vertex, VERB, i, state, nil, nil, first_string_in_vertex[first_string_in_vertex.index("/")+1..first_string_in_vertex.length])
-
elsif(first_string_in_vertex.include?("JJ"))
-
patterns[i].in_vertex = Vertex.new(in_vertex, ADJ, i, state, nil, nil, first_string_in_vertex[first_string_in_vertex.index("/")+1..first_string_in_vertex.length])
-
elsif(first_string_in_vertex.include?("/RB"))
-
patterns[i].in_vertex = Vertex.new(in_vertex, ADV, i, state, nil, nil, first_string_in_vertex[first_string_in_vertex.index("/")+1..first_string_in_vertex.length])
-
else #default to noun
-
patterns[i].in_vertex = Vertex.new(in_vertex, NOUN, i, state, nil, nil, first_string_in_vertex[first_string_in_vertex.index("/")+1..first_string_in_vertex.length])
-
end
-
-
#setting outvertex
-
if(first_string_out_vertex.include?("/NN") or first_string_out_vertex.include?("/PRP") or first_string_out_vertex.include?("/IN") or first_string_out_vertex.include?("/EX") or first_string_out_vertex.include?("/WP"))
-
patterns[i].out_vertex = Vertex.new(out_vertex, NOUN, i, state, nil, nil, first_string_out_vertex[first_string_out_vertex.index("/")+1..first_string_out_vertex.length])
-
elsif(first_string_out_vertex.include?("/VB") or first_string_out_vertex.include?("MD"))
-
patterns[i].out_vertex = Vertex.new(out_vertex, VERB, i, state, nil, nil, first_string_out_vertex[first_string_out_vertex.index("/")+1..first_string_out_vertex.length])
-
elsif(first_string_out_vertex.include?("JJ"))
-
patterns[i].out_vertex = Vertex.new(out_vertex, ADJ, i, state, nil, nil, first_string_out_vertex[first_string_out_vertex.index("/")+1..first_string_out_vertex.length-1]);
-
elsif(first_string_out_vertex.include?("/RB"))
-
patterns[i].out_vertex = Vertex.new(out_vertex, ADV, i, state, nil, nil, first_string_out_vertex[first_string_out_vertex.index("/")+1..first_string_out_vertex.length])
-
else #default is noun
-
patterns[i].out_vertex = Vertex.new(out_vertex, NOUN, i, state, nil, nil, first_string_out_vertex[first_string_out_vertex.index("/")+1..first_string_out_vertex.length])
-
end
-
i+=1 #incrementing for each pattern
-
end #end of the FasterCSV.foreach loop
-
num_patterns = i
-
return patterns
-
end
-
-
#------------------------------------------#------------------------------------------#------------------------------------------
-
-
=begin
-
Removes any urls in the text and returns the remaining text as it is
-
=end
-
1
def remove_urls(text)
-
final_text = String.new
-
if(text.include?("http://"))
-
tokens = text.split(" ")
-
tokens.each{
-
|token|
-
if(!token.include?("http://"))
-
final_text = final_text + " " + token
-
end
-
}
-
else
-
return text
-
end
-
return final_text
-
end
-
#------------------------------------------#------------------------------------------#------------------------------------------
-
-
=begin
-
Check for plagiarism after removing text within quotes for reviews
-
=end
-
1
def remove_text_within_quotes(review_text)
-
# puts "Inside removeTextWithinQuotes:: "
-
reviews = Array.new
-
review_text.each{ |row|
-
# puts "row #{row}"
-
text = row
-
#text = text[1..text.length-2] #since the first and last characters are quotes
-
#puts "text #{text}"
-
#the read text is tagged with two sets of quotes!
-
if(text.include?("\""))
-
while(text.include?("\"")) do
-
replace_text = text.scan(/"([^"]*)"/)
-
# puts "replace_text #{replace_text[0]}.. #{replace_text[0].to_s.class} .. #{replace_text.length}"
-
# puts text.index(replace_text[0].to_s)
-
# puts "replace_text length .. #{replace_text[0].to_s.length}"
-
#fetching the start index of the quoted text, in order to replace the complete segment
-
start_index = text.index(replace_text[0].to_s) - 1 #-1 in order to start from the quote
-
# puts "text[start_index..start_index + replace_text[0].to_s.length+1] .. #{text[start_index.. start_index + replace_text[0].to_s.length+1]}"
-
#replacing the text segment within the quotes (including the quotes) with an empty string
-
text.gsub!(text[start_index..start_index + replace_text[0].to_s.length+1], "")
-
# puts "text .. #{text}"
-
end #end of the while loop
-
end
-
reviews << text #set the text after all quoted segments have been removed.
-
} #end of the loop for "text" array
-
# puts "returning reviews length .. #{reviews.length}"
-
return reviews #return only the first array element - a string!
-
end
-
#------------------------------------------#------------------------------------------#------------------------------------------
-
=begin
-
Looks for spelling mistakes in the text and fixes them using the raspell library available for ruby
-
=end
-
1
def check_correct_spellings(review_text_array, speller)
-
review_text_array_temp = Array.new
-
#iterating through each response
-
review_text_array.each{
-
|review_text|
-
review_tokens = review_text.split(" ")
-
review_text_temp = ""
-
#iterating through tokens from each response
-
review_tokens.each{
-
|review_tok|
-
#checkiing the stem word's spelling for correctness
-
if(!speller.check(review_tok))
-
if(!speller.suggest(review_tok).first.nil?)
-
review_tok = speller.suggest(review_tok).first
-
end
-
end
-
review_text_temp = review_text_temp +" " + review_tok.downcase
-
}
-
review_text_array_temp << review_text_temp
-
}
-
return review_text_array_temp
-
end
-
-
#------------------------------------------#------------------------------------------#------------------------------------------
-
=begin
-
Checking if "str" is a punctuation mark like ".", ",", "?" etc.
-
=end
-
1
public #The method was throwing a "NoMethodError: private method" error when called from a different class. Hence the "public" keyword.
-
1
def contains_punct(str)
-
if(str.include?".")
-
str.gsub!(".","")
-
elsif(str.include?",")
-
str.gsub!(",","")
-
elsif(str.include?"?")
-
str.gsub!("?","")
-
elsif(str.include?"!")
-
str.gsub!("!","")
-
elsif(str.include?";")
-
str.gsub(";","")
-
elsif(str.include?":")
-
str.gsub!(":","")
-
elsif(str.include?"(")
-
str.gsub!("(","")
-
elsif(str.include?")")
-
str.gsub!(")","")
-
elsif(str.include?"[")
-
str.gsub!("[","")
-
elsif(str.include?"]")
-
str.gsub!("]","")
-
end
-
return str
-
end
-
-
1
def contains_punct_bool(str)
-
if(str.include?("\\n") or str.include?("}") or str.include?("{"))
-
return true
-
else
-
return false
-
end
-
end
-
-
#------------------------------------------#------------------------------------------#------------------------------------------
-
=begin
-
Checking if "str" is a punctuation mark like ".", ",", "?" etc.
-
=end
-
1
def is_punct(str)
-
if(str == "." or str == "," or str == "?" or str == "!" or str == ";" or str == ":")
-
return true
-
else
-
return false
-
end
-
end
-
-
end #end of class
-
1
require 'automated_metareview/wordnet_based_similarity'
-
1
require 'automated_metareview/text_preprocessing'
-
-
1
class TextQuantity
-
1
def number_of_unique_tokens(text_array)
-
pre_string = "" #preString helps keep track of the text that has been checked for unique tokens and text that has not
-
count = 0 #counts the number of unique tokens
-
instance = WordnetBasedSimilarity.new
-
text_array.each{
-
|text|
-
tp = TextPreprocessing.new
-
text = tp.contains_punct(text)
-
all_tokens = text.split(" ")
-
all_tokens.each{
-
|token|
-
if(!instance.is_frequent_word(token.downcase)) #do not count this word if it is a frequent word
-
if(!pre_string.downcase.include?(token.downcase)) #if the token was not already seen earlier i.e. not a part of the preString
-
count+=1
-
end
-
end
-
pre_string = pre_string +" " + token.downcase #adding token to the preString
-
}
-
}
-
return count
-
end
-
end
-
1
require 'automated_metareview/graph_generator'
-
1
require 'automated_metareview/wordnet_based_similarity'
-
1
require 'automated_metareview/constants'
-
-
1
class Tone
-
1
def identify_tone(pos_tagger, core_NLP_tagger, review_text, review_graph)
-
speller = Aspell.new("en_US")
-
speller.suggestion_mode = Aspell::NORMAL
-
-
cumulative_edge_feature = Array.new
-
cumulative_review_tone = Array.new
-
cumulative_review_tone = [-1, -1, -1] #sum of all edge tones
-
-
#extracting positive and negative words from files into arrays
-
positive_file = "app/models/automated_metareview/positive-words.csv"
-
negative_file = "app/models/automated_metareview/negative-words.csv"
-
positive = Array.new
-
negative = Array.new
-
FasterCSV.foreach(positive_file) do |text|
-
positive << text[0]
-
end
-
-
FasterCSV.foreach(negative_file) do |text|
-
negative << text[0]
-
end
-
-
negative = negative + NEGATIVE_DESCRIPTORS
-
review_edges = review_graph.edges
-
-
#if the edges are nil
-
if(review_edges.nil?)
-
return cumulative_review_tone
-
end
-
-
wbsim = WordnetBasedSimilarity.new
-
in_feature = Array.new
-
out_feature = Array.new
-
review_edges.each{
-
|edge|
-
if(!edge.nil?)
-
if(!edge.in_vertex.nil?)
-
# puts "#### Checking for edge #{edge.in_vertex.name}"
-
in_feature = get_feature_vector(edge.in_vertex, positive, negative, speller)
-
end
-
if(!edge.out_vertex.nil?)
-
# puts "#### with outvertex #{edge.out_vertex.name}"
-
out_feature = get_feature_vector(edge.out_vertex, positive, negative, speller)
-
end
-
-
# puts "in_feature :: [#{in_feature[0]}, #{in_feature[1]}]"
-
# puts "out_feature :: [#{out_feature[0]}, #{out_feature[1]}]"
-
-
#making sure that we don't include frequent tokens' tones while calculating cumulative edge tone (both + and -)
-
if(!wbsim.is_frequent_word(edge.in_vertex.name) and !wbsim.is_frequent_word(edge.out_vertex.name))
-
cumulative_edge_feature[0] = (in_feature[0].to_f + out_feature[0].to_f)/2.to_f
-
cumulative_edge_feature[1] = (in_feature[1].to_f + out_feature[1].to_f)/2.to_f
-
elsif(wbsim.is_frequent_word(edge.in_vertex.name) and !wbsim.is_frequent_word(edge.out_vertex.name))
-
cumulative_edge_feature[0] = out_feature[0].to_f
-
cumulative_edge_feature[1] = out_feature[1].to_f
-
elsif(!wbsim.is_frequent_word(edge.in_vertex.name) and wbsim.is_frequent_word(edge.out_vertex.name))
-
cumulative_edge_feature[0] = in_feature[0].to_f
-
cumulative_edge_feature[1] = in_feature[1].to_f
-
else
-
cumulative_edge_feature[0] = 0
-
cumulative_edge_feature[1] = 0
-
end
-
-
# puts "cumulative_edge_feature :: [#{cumulative_edge_feature[0]}, #{cumulative_edge_feature[1]}]"
-
if((cumulative_review_tone[0] == -1 and cumulative_review_tone[1] == -1) or
-
(cumulative_review_tone[0] == 0 and cumulative_review_tone[1] == 0)) #has not been initialized as yet
-
cumulative_review_tone[0] = cumulative_edge_feature[0].to_f
-
cumulative_review_tone[1] = cumulative_edge_feature[1].to_f
-
elsif(cumulative_edge_feature[0] > 0 or cumulative_edge_feature[1] > 0)
-
#only edges with some tone (either vertices) are taken into consideration during cumulative edge calculation
-
#else all edges will be considered, which may adversely affect the net tone of the review text
-
cumulative_review_tone[0] = (cumulative_review_tone[0].to_f + cumulative_edge_feature[0].to_f)/2.to_f
-
cumulative_review_tone[1] = (cumulative_review_tone[1].to_f + cumulative_edge_feature[1].to_f)/2.to_f
-
end
-
# puts "cumulative_review_tone :: [#{cumulative_review_tone[0]}, #{cumulative_review_tone[1]}]"
-
end
-
}
-
# puts "cumulative tone :: positive - #{cumulative_review_tone[0]}, negative - #{cumulative_review_tone[1]}"
-
if(cumulative_review_tone[0] == 0 and cumulative_review_tone[1] == 0)
-
cumulative_review_tone[2] = 1 #setting neutrality value
-
else
-
cumulative_review_tone[2] = 0
-
end
-
return cumulative_review_tone
-
end
-
#--------
-
1
def get_feature_vector(vertex, positive, negative, speller)
-
threshold = THRESHOLD #max distance at which synonyms can be searched
-
feature_vector = Array.new #size of the array depends on th number of tone dimensions e.g.[positive, negative, netural]
-
feature_vector = [0, 0] #initializing
-
#look for the presence of token in positive set
-
if(positive.include?(vertex.name.downcase))
-
feature_vector[0] = 1 #
-
else
-
#recursively check for synonyms of token in the positive set
-
distance = 1
-
flag = 0
-
synonym_sets = get_synonyms(vertex, threshold, speller) #gets upto 'threshold' levels of synonms in a double dimensional array
-
synonym_sets.each{
-
|set|
-
if(positive.length - (positive - set).length > 0)
-
feature_vector[0] = 1/distance
-
flag = 1
-
end
-
-
if(flag == 1)
-
break #break out of the loop
-
end
-
distance+=1 #incrementing to check synonyms in the next level
-
}
-
end
-
-
# repeat above with negative set
-
if(negative.include?(vertex.name.downcase))
-
feature_vector[1] = 1 #
-
else
-
#recursively check for synonyms of token in the positive set
-
distance = 1
-
flag = 0
-
synonym_sets = get_synonyms(vertex, threshold, speller) #gets upto 'threshold' levels of synonms in a double dimensional array
-
if(!synonym_sets[1].empty?)#i.e. if there were no synonyms identified for the token avoid rechecking for [0] - since that contains the original token
-
synonym_sets.each{
-
|set|
-
if(negative.length - (negative - set).length > 0)
-
feature_vector[1] = 1/distance
-
flag = 1
-
end
-
-
if(flag == 1)
-
break #break out of the loop
-
end
-
distance+=1 #incrementing to check synonyms in the next level
-
} #end of loop for synonym sets
-
end
-
end #end of if condition
-
-
return feature_vector
-
end
-
#--------
-
=begin
-
getSynonyms - gets synonyms for vertex - upto 'threshold' levels of synonyms
-
level 1 = token
-
level 2 = token's synonyms
-
...
-
level 'threshold' = synonyms of tokens in threshold - 1 level
-
=end
-
-
1
def get_synonyms(vertex, threshold, speller)
-
wbsim = WordnetBasedSimilarity.new
-
if(vertex.pos_tag.nil?)
-
pos = wbsim.determine_POS(vertex)
-
else
-
pos = vertex.pos_tag
-
end
-
-
revSyn = Array.new(threshold+1){Array.new} #contains synonyms for the different levels
-
revSyn[0] << vertex.name.downcase.split(" ")[0] #holds the array of tokens whose synonyms are to be identified,
-
# and what if the vertex had a long phrase
-
#at first level '0' is the token itself
-
i = 0
-
while i < threshold do
-
list_new = Array.new
-
revSyn[i].each{
-
|token|
-
lemmas = WordNet::WordNetDB.find(token) #reviewLemma = revIndex.find(revToken) #
-
if(lemmas.nil?)
-
lemmas = WordNet::WordNetDB.find(wbsim.findStemWord(token, speller)) #revIndex.find(revStem[0])
-
end
-
#select the lemma corresponding to the token's POS
-
lemma = lemmas[0] #set the first one as the default lemma, later if one with exact POS is found, set that as the lemma
-
lemmas.each do |l|
-
#puts "lemma's POS :: #{l.pos} and reviewPOS :: #{pos}"
-
if(l.pos.casecmp(pos) == 0)
-
lemma = l
-
end
-
end
-
-
#error handling for lemmas's without synsets that throw errors! (likely due to the dictionary file we are using)
-
#if selected reviewLemma is not nil or empty
-
if(!lemma.nil? and lemma != "" and !lemma.synsets.nil?)
-
#creating arrays of all the values for synonyms, hyponyms etc. for the review token
-
for g in 0..lemma.synsets.length - 1
-
#fetching the first review synset
-
review_lemma_synset = lemma.synsets[g]
-
#synonyms
-
begin #error handling
-
rev_lemma_syns = review_lemma_synset.get_relation("&")
-
#for each synset get the values and add them to the array
-
for h in 0..rev_lemma_syns.length - 1
-
#incrementing the array with new synonym words
-
list_new = list_new + rev_lemma_syns[h].words
-
end
-
rescue
-
list_new = nil
-
end
-
end
-
end #end of checking if the lemma is nil or empty
-
} #end of iterating through revSyn[level]'s tokens
-
-
if(list_new.nil? or list_new.empty?)
-
break
-
end
-
i+=1 #level is incremented
-
revSyn[i] = list_new #setting synonyms
-
end
-
return revSyn
-
end
-
end
-
1
class Vertex
-
#attr_accessor auto creates the get and set methods for the following attributes
-
1
attr_accessor :name, :type, :frequency, :index, :node_id, :state, :label, :parent, :pos_tag
-
1
def initialize(vertex_name, vertex_type, index_value, state, lab, par, pos_tag)
-
@name = vertex_name
-
@type = vertex_type
-
@frequency = 0
-
@index = index_value
-
@node_id = -1 #to identify if the id has been set or not
-
@state = state #they are not negated by default
-
-
#for semantic role labelling
-
@label = lab
-
@parent = par
-
-
@pos_tag = pos_tag
-
end
-
end
-
1
require 'automated_metareview/vertex'
-
1
require 'automated_metareview/constants'
-
-
1
class WordnetBasedSimilarity
-
1
attr_accessor :match, :count
-
1
@@posTagger = EngTagger.new
-
1
def compare_strings(reviewVertex, submVertex, speller)
-
#must fix this to something that is local to the app
-
# WordNet::WordNetDB.path = "/usr/local/WordNet-3.0"
-
# WordNet::WordNetDB.path = "/usr/local/Cellar/wordNet/3.0"
-
review = reviewVertex.name
-
submission = submVertex.name
-
reviewState = reviewVertex.state
-
submState = submVertex.state
-
-
# puts("@@@@@@@@@ Comparing Vertices:: #{review} and #{submission} :: RevState:: #{reviewState} and SubmState:: #{submState}");
-
@match = 0
-
@count = 0
-
-
reviewPOS = ""
-
submPOS = ""
-
-
#checking for exact matches between the tokens
-
if(review.casecmp(submission) == 0) # and !is_frequent_word(reviewVertex.name) - removing this condition else, it returns a NOMATCH although the frequent words are equal and this negatively impacts the total match value
-
# puts("Review vertex types #{reviewVertex.type} && #{submVertex.type}")
-
if(reviewState.equal?(submState))
-
@match = @match + EXACT
-
elsif(!reviewState.equal?(submState))
-
@match = @match + NEGEXACT
-
end
-
return @match
-
end
-
-
stokRev = review.split(" ")
-
#stokSub = submission.split(" ") #should've been inside when doing n * n comparison
-
-
#iterating through review tokens
-
for i in (0..stokRev.length-1)
-
#if either of the tokens is null
-
if(stokRev[i].nil?)
-
next #continue with the next token
-
end
-
revToken = stokRev[i].downcase()
-
if(reviewPOS.empty?)#do not reset POS for every new token, it changes the POS of the vertex e.g. like has diff POS for vertices "like"(n) and "would like"(v)
-
reviewPOS = determine_POS(reviewVertex).strip
-
end
-
-
# puts("*** RevToken:: #{revToken} ::Review POS:: #{reviewPOS} class #{reviewPOS.class}")
-
if(revToken.equal?("n't"))
-
revToken = "not"
-
# puts("replacing n't")
-
end
-
-
#if the review token is a frequent word, continue
-
if(is_frequent_word(revToken))
-
# puts("Skipping frequent review token .. #{revToken}")
-
next #equivalent of the "continue"
-
end
-
-
#fetching synonyms, hypernyms, hyponyms etc. for the review token
-
revStem = find_stem_word(revToken, speller)
-
#fetching all the relations
-
review_relations = get_relations_for_review_submission_tokens(revToken, revStem, reviewPOS)
-
#setting the values in specific array variables
-
revGloss = review_relations[0]
-
revSyn =review_relations[1]
-
revHyper = review_relations[2]
-
revHypo = review_relations[3]
-
revAnt = review_relations[4]
-
-
# puts "reviewStem:: #{revStem} .. #{revStem.class}"
-
# puts "reviewGloss:: #{revGloss} .. #{revGloss.class}"
-
# puts "reviewSynonyms:: #{revSyn} .. #{revSyn.class}"
-
# puts "reviewHypernyms:: #{revHyper} .. #{revHyper.class}"
-
# puts "reviewHyponyms:: #{revHypo} .. #{revHypo.class}"
-
# puts "reviewAntonyms:: #{revAnt} .. #{revAnt.class}"
-
-
stokSub = submission.split(" ")
-
#iterating through submission tokens
-
for j in (0..stokSub.length-1)
-
-
if(stokSub[i].nil?)
-
next
-
end
-
-
subToken = stokSub[j].downcase()
-
if(submPOS.empty?)#do not reset POS for every new token, it changes the POS of the vertex e.g. like has diff POS for vertices "like"(n) and "would like"(v)
-
submPOS = determine_POS(submVertex).strip
-
end
-
-
# puts("*** SubToken:: #{subToken} ::Review POS:: #{submPOS}")
-
if(subToken.equal?("n't"))
-
subToken = "not"
-
# puts("replacing n't")
-
end
-
-
#if the review token is a frequent word, continue
-
if(is_frequent_word(subToken))
-
# puts("Skipping frequent subtoken .. #{subToken}")
-
next #equivalent of the "continue"
-
end
-
-
#fetching synonyms, hypernyms, hyponyms etc. for the submission token
-
submStem = find_stem_word(subToken, speller)
-
subm_relations = get_relations_for_review_submission_tokens(subToken, submStem, submPOS)
-
submGloss = subm_relations[0]
-
submSyn =subm_relations[1]
-
submHyper = subm_relations[2]
-
submHypo = subm_relations[3]
-
submAnt = subm_relations[4]
-
# puts "submStem:: #{submStem}"
-
# puts "submGloss:: #{submGloss}"
-
# puts "submSynonyms:: #{submSyn}"
-
# puts "submHypernyms:: #{submHyper}"
-
# puts "submHyponyms:: #{submHypo}"
-
# puts "submAntonyms:: #{submAnt}"
-
-
#------------------------------------------
-
#checks are ordered from BEST to LEAST degree of semantic relatedness
-
#*****exact matches
-
# puts "@match #{@match} reviewState #{reviewState} submState #{submState} reviewPOS #{reviewPOS} submPOS #{submPOS}"
-
# puts "reviewState.equal?(submState) #{reviewState.equal?(submState)}"
-
# puts "reviewPOS.equal?(submPOS) #{reviewPOS == submPOS}"
-
if(subToken.casecmp(revToken) == 0 or submStem.casecmp(revStem) == 0) #EXACT MATCH (submission.toLowerCase().equals(review.toLowerCase()))
-
# puts("exact match for #{revToken} & #{subToken} or #{submStem} and #{revStem}")
-
if(reviewState.equal?(submState))
-
@match = @match + EXACT
-
elsif(!reviewState.equal?(submState))
-
@match = @match + NEGEXACT
-
end
-
@count+=1
-
next #skip all remaining checks
-
end #end of if condition checking for exact matches
-
#------------------------------------------
-
#*****For Synonyms
-
#if the method returns 'true' it indicates a synonym match of some kind was found and the remaining checks can be skipped
-
if(check_match(revToken, subToken, revSyn, submSyn, revStem, submStem, reviewState, submState, SYNONYM, ANTONYM))
-
next
-
end
-
#------------------------------------------
-
#ANTONYMS
-
if(check_match(revToken, subToken, revAnt, submAnt, revStem, submStem, reviewState, submState, ANTONYM, SYNONYM))
-
next
-
end
-
#------------------------------------------
-
#*****For Hypernyms
-
if(check_match(revToken, subToken, revHyper, submHyper, revStem, submStem, reviewState, submState, HYPERNYM, NEGHYPERNYM))
-
next
-
end
-
#------------------------------------------
-
#*****For Hyponyms
-
if(check_match(revToken, subToken, revHypo, submHypo, revStem, submStem, reviewState, submState, HYPONYM, NEGHYPONYM))
-
next
-
end
-
-
#overlap across definitions
-
# checking if overlaps exist across review and submission tokens' defintions or if either defintiions contains the review
-
# or submission token or stem.
-
# puts "#{extract_definition(revGloss)[0]} .. extract_definition(revGloss)[0] #{extract_definition(revGloss)[0][0].class}"
-
# puts "!revGloss #{!revGloss} .. revGloss.class #{revGloss.class}.. revGloss[0].include?(subToken) #{revGloss[0].include?(subToken)}"
-
# rev_def = extract_definition(revGloss)
-
# sub_def = extract_definition(submGloss)
-
#(!revGloss.nil? and !submGloss.nil? and overlap(revGloss, submGloss, speller) > 0) or
-
if((!revGloss.nil? and !revGloss[0].nil? and !subToken.nil? and !submStem.nil? and (revGloss[0].include?(subToken) or revGloss[0].include?(submStem))) or
-
(!submGloss.nil? and !submGloss[0].nil? and !revToken.nil? and !revStem.nil? and (submGloss[0].include?(revToken) or submGloss[0].include?(revStem))))
-
if(reviewState == submState)
-
@match = @match + OVERLAPDEFIN
-
elsif(reviewState != submState)
-
@match = @match + NEGOVERLAPDEFIN
-
end
-
@count+=1
-
next
-
end
-
-
#no match found!
-
# puts "No Match found!"
-
@match = @match + NOMATCH
-
@count+=1
-
end #end of the for loop for submission tokens
-
end #end of the for loop for review tokens
-
-
if(@count > 0)
-
# puts ("Match: #{@match} Count:: #{@count}")
-
result = (@match.to_f/@count.to_f).round
-
# puts("@@@@@@@@@ Returning Value: #{result}")
-
return result #an average of the matches found
-
end
-
# puts("@@@@@@@@@ Returning NOMATCH")
-
return NOMATCH
-
-
end #end of compareStrings method
-
-
#------------------------------------------------------------------------------
-
=begin
-
This method fetches the synonyms, hypernyms, hyponyms and other relations for the 'token' and its stem 'stem'.
-
This is done for both review and submission tokens/stems.
-
It returns a double dimensional array, where each element is an array of synonyms, hypernyms etc.
-
=end
-
-
1
def get_relations_for_review_submission_tokens(token, stem, pos)
-
# puts "@@@@ Inside get_relations_for_review_submission_tokens"
-
relations = Array.new
-
lemmas = WordNet::WordNetDB.find(token)
-
if(lemmas.nil?)
-
lemmas = WordNet::WordNetDB.find(stem)
-
end
-
#select the lemma corresponding to the token's POS
-
lemma = ""
-
lemmas.each do |l|
-
# puts "lemma's POS :: #{l.pos} and POS :: #{pos}"
-
if(l.pos == pos)
-
lemma = l
-
break
-
end
-
end
-
-
def_arr = Array.new
-
syn_arr = Array.new
-
hyper_arr = Array.new
-
hypo_arr = Array.new
-
anto_arr = Array.new
-
-
#if selected reviewLemma is not nil or empty
-
if(!lemma.nil? and lemma != "" and !lemma.synsets.nil?)
-
#creating arrays of all the values for synonyms, hyponyms etc. for the review token
-
for g in 0..lemma.synsets.length - 1
-
#fetching the first review synset
-
lemma_synset = lemma.synsets[g]
-
-
#definitions
-
if(!lemma_synset.gloss.nil?)
-
#puts "lemma_synset.gloss.class #{lemma_synset.gloss.class}"
-
if(def_arr[0].nil?)
-
def_arr << extract_definition(lemma_synset.gloss)
-
else
-
def_arr[0] = def_arr[0] + " " + extract_definition(lemma_synset.gloss)
-
end
-
else
-
def_arr << nil
-
end
-
-
#looking for all relations synonym, hypernym, hyponym etc. from among this synset
-
#synonyms
-
begin #error handling for lemmas's without synsets that throw errors! (likely due to the dictionary file we are using)
-
lemmaSyns = lemma_synset.get_relation("&")
-
if(!lemmaSyns.nil? and lemmaSyns.length != 0)
-
# puts "lemmaSyns.length #{lemmaSyns.length}"
-
#for each synset get the values and add them to the array
-
for h in 0..lemmaSyns.length - 1
-
# puts "lemmaSyns[h].words.class #{lemmaSyns[h].words.class}"
-
syn_arr = syn_arr + lemmaSyns[h].words
-
# puts "**** syn_arr #{syn_arr}"
-
end
-
else
-
syn_arr << nil #setting nil when no synset match is found for a particular type of relation
-
end
-
rescue
-
syn_arr << nil
-
end
-
-
#hypernyms
-
begin
-
lemmaHypers = lemma_synset.get_relation("@")#hypernym.words
-
if(!lemmaHypers.nil? and lemmaHypers.length != 0)
-
#for each synset get the values and add them to the array
-
for h in 0..lemmaHypers.length - 1
-
#puts "lemmaHypers[h].words.class #{lemmaHypers[h].words.class}"
-
hyper_arr = hyper_arr + lemmaHypers[h].words
-
end
-
else
-
hyper_arr << nil
-
end
-
rescue
-
hyper_arr << nil
-
end
-
-
#hyponyms
-
begin
-
lemmaHypos = lemma_synset.get_relation("~")#hyponym
-
if(!lemmaHypos.nil? and lemmaHypos.length != 0)
-
#for each synset get the values and add them to the array
-
for h in 0..lemmaHypos.length - 1
-
hypo_arr = hypo_arr + lemmaHypos[h].words
-
end
-
else
-
hypo_arr << nil
-
end
-
rescue
-
hypo_arr << nil
-
end
-
-
#antonyms
-
begin
-
lemmaAnts = lemma_synset.get_relation("!")
-
if(!lemmaAnts.nil? and lemmaAnts.length != 0)
-
#for each synset get the values and add them to the array
-
for h in 0..lemmaAnts.length - 1
-
anto_arr = anto_arr + lemmaAnts[h].words
-
end
-
else
-
anto_arr << nil
-
end
-
rescue
-
anto_arr << nil
-
end
-
end #end of the for loop for g
-
end #end of checking if the lemma is nil or empty
-
-
#setting the array elements before returning the array
-
relations << def_arr
-
relations << syn_arr
-
relations << hyper_arr
-
relations << hypo_arr
-
relations << anto_arr
-
return relations
-
end
-
-
#------------------------------------------------------------------------------
-
=begin
-
This method compares the submission and reviews' synonyms and antonyms with each others' tokens and stem values.
-
The instance variables 'match' and 'count' are updated accordingly.
-
=end
-
1
def check_match(rev_token, subm_token, rev_arr, subm_arr, rev_stem, subm_stem, rev_state, subm_state, match_type, non_match_type)
-
flag = 0 #indicates if a match was found
-
# puts("check_match between: #{rev_token} & #{subm_token} match_type #{match_type} and non_match_type #{non_match_type}")
-
# puts "rev_arr #{rev_arr}"
-
# puts "subm_arr #{subm_arr}"
-
if((!rev_arr.nil? and (rev_arr.include?(subm_token) or rev_arr.include?(subm_stem))) or
-
(!subm_arr.nil? and (subm_arr.include?(rev_token) or subm_arr.include?(rev_stem))))
-
# puts("Match found between: #{rev_token} & #{subm_token}")
-
flag = 1 #setting the flag to indicate that a match was found
-
if(rev_state == subm_state)
-
@match = @match + match_type
-
elsif(rev_state != subm_state)
-
@match = @match+ non_match_type
-
end
-
@count+=1
-
end
-
if(flag == 1)
-
return true
-
else
-
return false
-
end
-
end
-
-
#------------------------------------------------------------------------------
-
-
=begin
-
determine_POS - method helps identify the POS tag (for the wordnet lexicon) for a certain word
-
=end
-
1
def determine_POS(vert)
-
str_pos = vert.pos_tag
-
# puts("Inside determine_POS POS Tag:: #{str_pos}")
-
if(str_pos.include?("CD") or str_pos.include?("NN") or str_pos.include?("PR") or str_pos.include?("IN") or str_pos.include?("EX") or str_pos.include?("WP"))
-
pos = "n"#WordNet::Noun
-
elsif(str_pos.include?("JJ"))
-
pos = "a" #WordNet::Adjective
-
elsif(str_pos.include?("TO") or str_pos.include?("VB") or str_pos.include?("MD"))
-
pos = "v" #WordNet::Verb
-
elsif(str_pos.include?("RB"))
-
pos = "r" #WordNet::Adverb
-
else
-
pos = "n" #WordNet::Noun
-
end
-
return pos
-
end
-
-
#------------------------------------------------------------------------------
-
=begin
-
is_frequent_word - method checks to see if the given word is a frequent word
-
=end
-
1
def is_frequent_word(word)
-
word.gsub!("(", "") #gsub replaces all occurrences of "(" and the exclamation point helps to do in-place substitution
-
word.gsub!(")", "") #if the character doesn't exist, the function returns nil, which does not affect the existing variable
-
word.gsub!("[", "")
-
word.gsub!("]", "")
-
word.gsub!("\"", "")
-
-
if(FREQUENT_WORDS.include?(word))
-
return true
-
end
-
-
if(CLOSED_CLASS_WORDS.include?(word))
-
return true
-
end
-
-
return false
-
end #end of is_frequent_word method
-
#------------------------------------------------------------------------------
-
=begin
-
find_stem_word - stems the word and checks if the word is correctly spelt, else it will return a correctly spelled word as suggested by spellcheck
-
It generated the nearest stem, since no context information is involved, the quality of the stems may not be great!
-
=end
-
1
def find_stem_word(word, speller)
-
stem = word.stem
-
correct = stem #initializing correct to the stem word
-
#checkiing the stem word's spelling for correctness
-
while(!speller.check(correct)) do
-
if(!speller.suggest(correct).first.nil?)
-
correct = speller.suggest(correct).first
-
else
-
#break out of the loop, else it will continue infinitely
-
break #break out of the loop if the first correction was nil
-
end
-
end
-
return correct
-
end #end of is_frequent_word method
-
-
#------------------------------------------------------------------------------
-
-
=begin
-
This method is used to extract definitions for the words (since glossed contain definitions and examples!)
-
glosses - string containing the gloss of the synset
-
=end
-
1
def extract_definition(glosses)
-
definitions = ""#[]
-
#extracting examples from definitions
-
temp = glosses
-
tempList = temp.split(";")
-
for i in 0..tempList.length - 1
-
if(!tempList[i].include?('"'))
-
if(definitions.empty?)
-
definitions = tempList[i]
-
else
-
definitions = definitions +" "+ tempList[i]
-
end
-
end
-
end
-
#puts definitions
-
return definitions
-
end
-
#------------------------------------------------------------------------------
-
-
1
def overlap(def1, def2, speller)
-
instance = WordnetBasedSimilarity.new
-
numOverlap = 0
-
#only overlaps across the ALL definitions
-
# puts "def1 #{def1}"
-
# puts "def2 #{def2}"
-
-
#iterating through def1's definitions
-
for i in 0..def1.length-1
-
if(!def1[i].nil?)
-
#puts "def1[#{i}] #{def1[i]}"
-
if( def1[i].include?("\""))
-
def1[i].gsub!("\"", " ")
-
end
-
if(def1[i].include?(";"))
-
def1[i] = def1[i][0..def1[i].index(";")]
-
end
-
#iterating through def2's definitions
-
for j in 0..def2.length - 1
-
if(!def2[j].nil?)
-
if(def2[j].include?(";"))
-
def2[j] = def2[j][0..def2[j].index(";")]
-
end
-
#puts "def2[#{j}] #{def2[j]}"
-
s1 = def1[i].split(" ")
-
s1.each do |tok1|
-
tok1stem = find_stem_word(tok1, speller)
-
s2 = def2[j].split(" ")
-
s2.each do |tok2|
-
tok2stem = find_stem_word(tok2, speller)
-
# puts "tok1 #{tok1} and tok2 #{tok2}"
-
# puts "tok1stem #{tok1stem} and tok2stem #{tok2stem}"
-
if((tok1.downcase == tok2.downcase or tok1stem.downcase == tok2stem.downcase) and
-
!instance.is_frequent_word(tok1) and !instance.is_frequent_word(tok1stem))
-
# puts("**Overlap def/ex:: #{tok1} or #{tok1stem}")
-
numOverlap+=1
-
end
-
end #end of s2 loop
-
end #end of s1 loop
-
end #end of def2[j][0] being null
-
end #end of for loop for def2 - j
-
end #end of if def1[i][0] being null
-
end #end of for loop for def1 - i
-
return numOverlap
-
end
-
#------------------------------------------------------------------------------
-
end #end of WordnetBasedSimilarity class
-
1
class Comment < ActiveRecord::Base
-
1
belongs_to :participant
-
end
-
1
require 'redcloth'
-
-
1
class ContentPage < ActiveRecord::Base
-
1
validates_presence_of :name
-
1
validates_uniqueness_of :name
-
-
1
belongs_to :permission
-
-
1
attr_accessor :content_html
-
-
1
def self.find_for_permission(p_ids)
-
where('permission_id in (?)', p_ids)
-
.order(:name)
-
end
-
-
1
def url
-
"/#{self.name}"
-
end
-
-
1
def markup_style
-
if !@markup_style && markup_style_id && markup_style_id > 0
-
@markup_style = MarkupStyle.find markup_style_id
-
end
-
end
-
-
1
def before_save
-
self.content_cache = markup_content
-
end
-
-
1
def content_html
-
11
if content_cache && content_cache.length > 0
-
11
content_cache.html_safe
-
else
-
markup_content.html_safe
-
end
-
end
-
-
1
protected
-
-
1
def markup_content
-
markup = self.markup_style
-
if markup and markup.name
-
if markup.name == 'Textile'
-
content_html = RedCloth.new(self.content).to_html(:textile)
-
elsif markup.name == 'Markdown'
-
content_html = RedCloth.new(self.content).to_html(:markdown)
-
else
-
content_html = self.content
-
end
-
else
-
content_html = self.content
-
end
-
return content_html
-
end
-
end
-
1
class ControllerAction < ActiveRecord::Base
-
1
belongs_to :site_controller
-
1
belongs_to :permission
-
-
1
validates_presence_of :name
-
1
validates_uniqueness_of :name, :scope => 'site_controller_id'
-
-
1
attr_accessor :controller, :permission, :url, :allowed, :specific_name
-
-
1
scope :order_by_controller_and_action, -> {
-
joins('left outer join site_controllers on site_controller_id = site_controllers.id').
-
order('site_controllers.name, name')
-
}
-
-
1
def controller
-
5958
@controller ||= SiteController.find(self.site_controller_id)
-
end
-
-
1
def permission
-
if not @permission
-
if self.permission_id
-
@permission = Permission.find_by_id(self.permission_id)
-
else
-
@permission = Permission.new(:id => nil,
-
:name => "(default -- #{self.controller.permission.name})")
-
end
-
end
-
return @permission
-
end
-
-
1
def effective_permission_id
-
667
return self.permission_id || self.controller.permission_id
-
end
-
-
1
def fullname
-
if self.site_controller_id and self.site_controller_id > 0
-
return "#{self.controller.name}: #{self.name}"
-
else
-
return "#{self.name}"
-
end
-
end
-
-
1
def url
-
@url ||= "/#{self.controller.name}/#{self.name}"
-
return @url
-
end
-
-
1
def self.actions_allowed(permission_ids)
-
# Hash for faster & easier lookups
-
23
if permission_ids
-
23
perms = {}
-
23
for id in permission_ids do
-
507
perms[id] = true
-
end
-
end
-
-
23
actions = ControllerAction.find(:all)
-
23
for action in actions do
-
2070
if action.permission_id
-
1380
if perms.has_key?(action.permission_id)
-
1072
action.allowed = 1
-
else
-
308
action.allowed = 0
-
end
-
else # Controller's permission
-
690
if perms.has_key?(action.controller.permission_id)
-
351
action.allowed = 1
-
else
-
339
action.allowed = 0
-
end
-
end
-
end
-
-
23
return actions
-
end
-
-
1
def self.find_for_permission(p_ids)
-
if p_ids and p_ids.length > 0
-
return find(:all,
-
:conditions => ['permission_id in (?)', p_ids],
-
:order => 'name')
-
else
-
return Array.new
-
end
-
end
-
-
end
-
1
class Course < ActiveRecord::Base
-
1
has_many :ta_mappings
-
1
validates_presence_of :name
-
1
has_many :assignments, :dependent => :destroy
-
1
belongs_to :instructor, :class_name => 'User', :foreign_key => 'instructor_id'
-
1
has_many :participants, :class_name => 'CourseParticipant', :foreign_key => 'parent_id'
-
-
# Return any predefined teams associated with this course
-
# Author: ajbudlon
-
# Date: 7/21/2008
-
1
def get_teams
-
return CourseTeam.find_all_by_parent_id(self.id)
-
end
-
-
#Returns this object's submission directory
-
1
def get_path
-
if self.instructor_id == nil
-
raise "Path can not be created. The course must be associated with an instructor."
-
end
-
return RAILS_ROOT + "/pg_data/" + FileHelper.clean_path(User.find(self.instructor_id).name)+ "/" + FileHelper.clean_path(self.directory_path) + "/"
-
end
-
-
1
def get_participants
-
CourseParticipant.find_all_by_parent_id(self.id)
-
end
-
-
1
def get_participant (user_id)
-
CourseParticipant.find_all_by_parent_id_and_user_id(self.id, user_id)
-
end
-
-
1
def add_participant(user_name)
-
user = User.find_by_name(user_name)
-
if (user == nil)
-
raise "No user account exists with the name "+user_name+". Please <a href='"+url_for(:controller => 'users', :action => 'new')+"'>create</a> the user first."
-
end
-
participant = CourseParticipant.find_by_parent_id_and_user_id(self.id, user.id)
-
unless participant # If there is already a participant, it has already been added. done. Otherwise, create it
-
CourseParticipant.create(:parent_id => self.id, :user_id => user.id, :permission_granted => user.master_permission_granted)
-
end
-
end
-
-
1
def copy_participants(assignment_id)
-
participants = AssignmentParticipant.find_all_by_parent_id(assignment_id)
-
errors = Array.new
-
error_msg = String.new
-
participants.each {
-
|participant|
-
user = User.find(participant.user_id)
-
-
begin
-
self.add_participant(user.name)
-
rescue
-
errors << $!
-
end
-
}
-
if errors.length > 0
-
errors.each {
-
|error|
-
if error
-
error_msg = error_msg+"<BR/>"+error
-
end
-
}
-
raise error_msg
-
end
-
end
-
-
1
require 'analytic/course_analytic'
-
1
include CourseAnalytic
-
end
-
1
class CourseEvaluationQuestionnaire < Questionnaire
-
1
def after_initialize
-
self.display_type = 'Course Evaluation'
-
end
-
end
-
1
class CourseNode < Node
-
1
belongs_to :course, :class_name => "Course", :foreign_key => "node_object_id"
-
1
belongs_to :node_object, :class_name => "Course"
-
-
# Returns the table in which to locate Courses
-
1
def self.table
-
"courses"
-
end
-
-
# parameters:
-
# sortvar: valid strings - name, created_at, updated_at, directory_path
-
# sortorder: valid strings - asc, desc
-
# user_id: instructor id for Course
-
# parent_id: not used for this type of object
-
-
# returns: list of CourseNodes based on query
-
# the get method will return all courses meeting the criteria, but the method name is necessary due to polymorphism
-
1
def self.get(sortvar = 'name',sortorder ='ASC',user_id = nil,show = nil, parent_id = nil)
-
65
find(:all, :include => :course, :conditions => [get_course_query_conditions(show, user_id), get_courses_managed_by_user(user_id)], :order => "courses.#{sortvar} #{sortorder}")
-
end
-
-
#get the query conditions for a public course
-
1
def self.get_course_query_conditions(show = nil, user_id = nil)
-
65
this_user = User.find(user_id)
-
-
65
if show
-
65
if this_user.is_teaching_assistant? == false
-
65
conditions = 'courses.instructor_id = ?'
-
else
-
conditions = 'courses.id in (?)'
-
end
-
else
-
if this_user.is_teaching_assistant? == false
-
conditions = '(courses.private = 0 or courses.instructor_id = ?)'
-
else
-
conditions = '(courses.private = 0 or courses.id in (?))'
-
end
-
end
-
-
65
return conditions
-
end
-
-
#get the courses managed by the user
-
1
def self.get_courses_managed_by_user(user_id = nil)
-
65
this_user = User.find(user_id)
-
-
65
if this_user.is_teaching_assistant? == false
-
65
values = user_id
-
else
-
values = Ta.get_mapped_courses(user_id)
-
end
-
-
65
return values
-
end
-
-
# get parent id
-
1
def self.get_parent_id
-
folder = TreeFolder.find_by_name('Courses')
-
parent = FolderNode.find_by_node_object_id(folder.id)
-
if parent
-
return parent.id
-
else
-
return nil
-
end
-
end
-
-
# Gets any children associated with this object
-
# the get_children method will return assignments belonging to a course, but the method name is necessary due to polymorphism
-
1
def get_children(sortvar = nil,sortorder =nil,user_id = nil,show = nil, parent_id = nil)
-
AssignmentNode.get(sortvar,sortorder,user_id,show,self.node_object_id)
-
end
-
-
# Gets the name from the associated object
-
1
def get_name
-
Course.find(self.node_object_id).name
-
end
-
-
# Gets the directory_path from the associated object
-
1
def get_directory
-
Course.find(self.node_object_id).directory_path
-
end
-
-
# Gets the created_at from the associated object
-
1
def get_creation_date
-
Course.find(self.node_object_id).created_at
-
end
-
-
# Gets the updated_at from the associated object
-
1
def get_modified_date
-
Course.find(self.node_object_id).updated_at
-
end
-
-
# Gets any TeamNodes associated with this object
-
1
def get_teams
-
TeamNode.get(self.node_object_id)
-
end
-
-
end
-
1
class CourseParticipant < Participant
-
1
belongs_to :course, :class_name => 'Course', :foreign_key => 'parent_id'
-
-
# Copy this participant to an assignment
-
1
def copy(assignment_id)
-
part = AssignmentParticipant.find_by_user_id_and_parent_id(self.user_id,assignment_id)
-
if part.nil?
-
newpart = AssignmentParticipant.create(:user_id => self.user_id, :parent_id => assignment_id)
-
newpart.set_handle()
-
end
-
end
-
-
# provide import functionality for Course Participants
-
# if user does not exist, it will be created and added to this assignment
-
1
def self.import(row,session,id)
-
if row.length != 4
-
raise ArgumentError, "The record containing #{row[0]} should have 4 items, it has #{row.length}."
-
end
-
user = User.find_by_name(row[0])
-
if (user == nil)
-
attributes = ImportFileHelper::define_attributes(row)
-
user = ImportFileHelper::create_new_user(attributes,session)
-
end
-
course = Course.find(id)
-
if course == nil
-
raise ImportError, "The course with id \""+id.to_s+"\" was not found."
-
end
-
if (find(:all, {:conditions => ['user_id=? AND parent_id=?', user.id, course.id]}).size == 0)
-
create(:user_id => user.id, :parent_id => course.id)
-
end
-
end
-
-
1
def get_course_string
-
# if no course is associated with this assignment, or if there is a course with an empty title, or a course with a title that has no printing characters ...
-
if self.course == nil or self.course.name == nil or self.course.name.strip == ""
-
return "<center>—</center>"
-
end
-
return self.course.name
-
end
-
-
1
def get_path
-
Course.find(self.parent_id).get_path + self.directory_num.to_s + "/"
-
end
-
-
# provide export functionality for Assignment Participants
-
1
def self.export(csv, parent_id, options)
-
find_all_by_parent_id(parent_id).each {
-
|part|
-
tcsv = Array.new
-
user = part.user
-
if (options["personal_details"] == "true")
-
tcsv.push(user.name, user.fullname, user.email)
-
end
-
if (options["role"] == "true")
-
tcsv.push(user.role.name)
-
end
-
if (options["parent"] == "true")
-
tcsv.push(user.parent.name)
-
end
-
if (options["email_options"] == "true")
-
tcsv.push(user.email_on_submission, user.email_on_review, user.email_on_review_of_review)
-
end
-
if (options["handle"] == "true")
-
tcsv.push(part.handle)
-
end
-
csv << tcsv
-
}
-
end
-
-
1
def self.get_export_fields(options)
-
fields = Array.new
-
if (options["personal_details"] == "true")
-
fields.push("name", "full name", "email")
-
end
-
if (options["role"] == "true")
-
fields.push("role")
-
end
-
if (options["parent"] == "true")
-
fields.push("parent")
-
end
-
if (options["email_options"] == "true")
-
fields.push("email on submission", "email on review", "email on metareview")
-
end
-
if (options["handle"] == "true")
-
fields.push("handle")
-
end
-
return fields
-
end
-
-
end
-
1
class CourseTeam < Team
-
1
belongs_to :course, :class_name => 'Course', :foreign_key => 'parent_id'
-
-
#NOTE: inconsistency in naming of users that's in the team
-
# currently they are being called: member, participant, user, etc...
-
# suggestion: refactor all to participant
-
-
1
def get_participant_type
-
"CourseParticipant"
-
end
-
-
1
def get_parent_model
-
"Course"
-
end
-
-
1
def get_node_type
-
"TeamNode"
-
end
-
-
# since this team is not an assignment team, the assignment_id is nil.
-
1
def assignment_id
-
nil
-
end
-
-
1
def copy(assignment_id)
-
new_team = AssignmentTeam.create_team_and_node(assignment_id)
-
new_team.name = name
-
new_team.save
-
copy_members(new_team)
-
end
-
-
#deprecated: the functionality belongs to course
-
1
def add_participant(course_id, user)
-
if CourseParticipant.find_by_parent_id_and_user_id(course_id, user.id) == nil
-
CourseParticipant.create(:parent_id => course_id, :user_id => user.id, :permission_granted => user.master_permission_granted)
-
end
-
end
-
-
1
def export_participants
-
userNames = Array.new
-
participants = TeamsUser.find(:all, :conditions => ['team_id = ?', self.id])
-
participants.each do |participant|
-
userNames.push(participant.name)
-
userNames.push(" ")
-
end
-
return userNames
-
end
-
-
1
def export(team_name_only)
-
output = Array.new
-
output.push(self.name)
-
if team_name_only == "false"
-
output.push(self.export_participants)
-
end
-
course = Course.find(self.parent_id)
-
output.push(course.name)
-
return output
-
end
-
-
1
def self.handle_duplicate(team, name, course_id, handle_dups)
-
puts ">>>at beginning of handle_duplicate, name = "+ name
-
puts ">>>at beginning of handle_duplicate, handle_dups = "+ handle_dups
-
if team.nil? #no duplicate
-
return name
-
end
-
if handle_dups == "ignore" #ignore: do not create the new team
-
p '>>>setting name to nil ...'
-
return nil
-
end
-
if handle_dups == "rename" #rename: rename new team
-
return self.generate_team_name(Course.find(course_id).name)
-
end
-
if handle_dups == "replace" #replace: delete old team
-
team.delete
-
return name
-
else # handle_dups = "insert"
-
return nil
-
end
-
end
-
-
#TODO: unused variable session
-
1
def self.import(row,session,course_id,options)
-
if (row.length < 2 and options[:has_column_names] == "true") or (row.length < 1 and options[:has_column_names] != "true")
-
raise ArgumentError, "Not enough fields on this line"
-
end
-
-
if Course.find(course_id) == nil
-
raise ImportError, "The course with id \""+course_id.to_s+"\" was not found. <a href='/assignment/new'>Create</a> this course?"
-
end
-
-
if options[:has_column_names] == "true"
-
name = row[0].to_s.strip
-
team = find(:first, :conditions => ["name =? and parent_id =?", name, course_id])
-
team_exists = !team.nil?
-
name = handle_duplicate(team, name, course_id, options[:handle_dups])
-
index = 1
-
else
-
name = self.generate_team_name(Course.find(course_id).name)
-
index = 0
-
end
-
-
# handle_dups == "rename" ||" replace"
-
# create new team for the team to be inserted
-
if name
-
team=CourseTeam.create_team_and_node(course_id)
-
team.name = name
-
team.save
-
end
-
-
# handle_dups == "rename" ||" replace" || "insert"
-
# insert team members into team unless team was pre-existing & we ignore duplicate teams
-
if !(team_exists && options[:handle_dups] == "ignore")
-
team.import_team_members(index, row)
-
end
-
end
-
-
1
def self.export(csv, parent_id, options)
-
course = Course.find(parent_id)
-
if course.nil?
-
raise ImportError, "The course with id \""+course_id.to_s+"\" was not found. <a href='/assignment/new'>Create</a> this course?"
-
end
-
-
teams = CourseTeam.find_all_by_parent_id(parent_id)
-
teams.each do |team|
-
csv << team.export(options[:team_name])
-
end
-
end
-
-
1
def self.get_export_fields(options)
-
fields = Array.new
-
fields.push("Team Name")
-
if (options[:team_name] == "false")
-
fields.push("Team members")
-
end
-
fields.push("Course Name")
-
end
-
-
#deprecated: this is the original self.export function
-
# if this is a desired export behavior than
-
# it should either belong to course class or assignment team class
-
1
def self.export_all_assignment_team_related_to_course(csv, parent_id, options)
-
course = Course.find(parent_id)
-
assignmentList = Assignment.find_all_by_course_id(parent_id)
-
assignmentList.each do |currentAssignment|
-
currentAssignment.teams.each { |team|
-
tcsv = Array.new
-
teamUsers = Array.new
-
tcsv.push(team.name)
-
if (options["team_name"] == "true")
-
teamMembers = TeamsUser.find(:all, :conditions => ['team_id = ?', team.id])
-
teamMembers.each do |user|
-
teamUsers.push(user.name)
-
teamUsers.push(" ")
-
end
-
tcsv.push(teamUsers)
-
end
-
tcsv.push(currentAssignment.name)
-
tcsv.push(course.name)
-
csv << tcsv
-
}
-
end
-
end
-
-
1
def self.create_team_and_node(course_id)
-
course = Course.find(course_id)
-
teamname = Team.generate_team_name(course.name)
-
team = CourseTeam.create(:name=>teamname, :parent_id => course_id)
-
TeamNode.create(:parent_id =>course_id,:node_object_id=>team.id)
-
team
-
end
-
end
-
1
class CoursesUsers < ActiveRecord::Base
-
# provide import functionality for Course Users
-
# if user does not exist, it will be created and added to this course
-
1
def self.import(row,session,id)
-
if row.length != 4
-
raise ArgumentError, "Not enough items"
-
end
-
user = User.find_by_name(row[0])
-
if (user == nil)
-
attributes = ImportFileHelper::define_attributes(row)
-
user = ImportFileHelper::create_new_user(attributes,session)
-
end
-
if id == nil
-
raise MissingObjectIDError
-
end
-
course = Course.find(id)
-
if course == nil
-
raise ImportError, "The course with id \""+id.to_s+"\" was not found."
-
end
-
if (CoursesUsers.find(:all, {:conditions => ['user_id=? AND course_id=?', user.id, course.id]}).size == 0)
-
CoursesUsers.create :user_id => user.id, :course_id => course.id
-
end
-
end
-
-
1
def email(pw, home_page)
-
user = User.find_by_id(self.user_id)
-
course = Course.find_by_id(self.course_id)
-
Mailer.deliver_message(
-
{:recipients => user.email,
-
:subject => "You have been registered as a participant in #{course.title}",
-
:body => {
-
:home_page => home_page,
-
:user_name => ApplicationHelper::get_user_first_name(user),
-
:name =>user.name,
-
:password =>pw,
-
:partial_name => "register"
-
}
-
}
-
)
-
end
-
-
end
-
1
class Credentials
-
-
1
attr_accessor :role_id, :updated_at, :role_ids
-
1
attr_accessor :permission_ids
-
1
attr_accessor :controllers, :actions, :pages
-
-
# Create a new credentials object for the given role
-
1
def initialize(role_id)
-
23
@role_id = role_id
-
-
23
role = Role.find(@role_id)
-
23
@updated_at = role.updated_at
-
-
90
@role_ids = role.get_parents.map{|r|r.id}
-
-
23
permissions = Permission.find_for_role(@role_ids)
-
528
@permission_ids = permissions.map{|p|p.id}
-
-
23
if @permission_ids.empty?
-
2
@permission_ids << 0
-
end
-
-
# actions = ControllerAction.find_by_sql ["select *, (case when permission_id in (?) then 1 else 0 end) as allowed from view_controller_actions",
-
# @permission_ids]
-
23
actions = ControllerAction.actions_allowed(@permission_ids)
-
23
@actions = Hash.new
-
23
for a in actions do
-
2070
@actions[a.controller.name] ||= Hash.new
-
2070
if a.allowed.to_i == 1
-
1423
@actions[a.controller.name][a.name] = true
-
else
-
647
@actions[a.controller.name][a.name] = false
-
end
-
end
-
-
23
controllers = SiteController.find_by_sql ["select *, (case when permission_id in (?) then 1 else 0 end) as allowed from site_controllers",
-
@permission_ids]
-
23
@controllers = Hash.new
-
23
for c in controllers do
-
1173
if c.allowed.to_i == 1
-
707
@controllers[c.name] = true
-
else
-
466
@controllers[c.name] = false
-
end
-
end
-
-
23
pages = ContentPage.find_by_sql ["select id, name, permission_id, (case when permission_id in (?) then 1 else 0 end) as allowed from content_pages",
-
@permission_ids]
-
23
@pages = Hash.new
-
23
for p in pages do
-
184
if p.allowed.to_i == 1
-
143
@pages[p.name] = true
-
else
-
41
@pages[p.name] = false
-
end
-
end
-
-
end
-
-
end
-
1
class CsEntriesAdaptor
-
1
attr_accessor :participant_id
-
1
attr_accessor :total_score
-
1
attr_accessor :questionnaire_id
-
end
-
1
class DeadlineRight < ActiveRecord::Base
-
end
-
1
class DeadlineType < ActiveRecord::Base
-
end
-
1
class DisplayOption
-
1
attr_accessor :name
-
end
-
1
class DueDate < ActiveRecord::Base
-
1
belongs_to :assignment
-
1
belongs_to :deadline_type
-
1
validate :due_at_is_valid_datetime
-
-
1
def self.default_permission(deadline_type, permission_type)
-
permission_id = Hash.new
-
permission_id['OK'] = DeadlineRight.find_by_name('OK').id
-
permission_id['No'] = DeadlineRight.find_by_name('No').id
-
permission_id['Late'] = DeadlineRight.find_by_name('Late').id
-
-
default_permission = Hash.new
-
default_permission['submission'] = Hash.new
-
default_permission['submission']['submission_allowed'] = permission_id['OK']
-
default_permission['submission']['review_allowed'] = permission_id['No']
-
default_permission['submission']['review_of_review_allowed'] = permission_id['No']
-
-
default_permission['review'] = Hash.new
-
default_permission['review']['submission_allowed'] = permission_id['No']
-
default_permission['review']['review_allowed'] = permission_id['OK']
-
default_permission['review']['review_of_review_allowed'] = permission_id['No']
-
-
default_permission['metareview'] = Hash.new
-
default_permission['metareview']['submission_allowed'] = permission_id['No']
-
default_permission['metareview']['review_allowed'] = permission_id['No']
-
default_permission['metareview']['review_of_review_allowed'] = permission_id['OK']
-
-
default_permission['drop_topic'] = Hash.new
-
default_permission['drop_topic']['submission_allowed'] = permission_id['OK']
-
default_permission['drop_topic']['review_allowed'] = permission_id['No']
-
default_permission['drop_topic']['review_of_review_allowed'] = permission_id['No']
-
-
default_permission['signup'] = Hash.new
-
default_permission['signup']['submission_allowed'] = permission_id['OK']
-
default_permission['signup']['review_allowed'] = permission_id['No']
-
default_permission['signup']['review_of_review_allowed'] = permission_id['No']
-
-
default_permission['team_formation'] = Hash.new
-
default_permission['team_formation']['submission_allowed'] = permission_id['OK']
-
default_permission['team_formation']['review_allowed'] = permission_id['No']
-
default_permission['team_formation']['review_of_review_allowed'] = permission_id['No']
-
-
default_permission[deadline_type][permission_type]
-
end
-
-
1
def type
-
self.deadline_type.name
-
end
-
-
1
def due_at_is_valid_datetime
-
unless due_at.blank?
-
errors.add(:due_at, 'must be a valid datetime') if ((DateTime.strptime(due_at.to_s, '%Y-%m-%d %H:%M:%S') rescue ArgumentError) == ArgumentError)
-
end
-
end
-
-
1
def self.copy(old_assignment_id, new_assignment_id)
-
duedates = find(:all, :conditions => ['assignment_id = ?', old_assignment_id])
-
duedates.each do |orig_due_date|
-
new_due_date = orig_due_date.clone
-
new_due_date.assignment_id = new_assignment_id
-
new_due_date.save
-
end
-
end
-
-
1
def self.set_duedate (duedate, deadline, assign_id, max_round)
-
submit_duedate=DueDate.new(duedate)
-
submit_duedate.deadline_type_id = deadline
-
submit_duedate.assignment_id = assign_id
-
submit_duedate.round = max_round
-
submit_duedate.save
-
end
-
-
1
def setFlag()
-
#puts"~~~~~~~~~enter setFlag"
-
self.flag = true
-
self.save
-
#puts"~~~~~~~~~#{self.flag.to_s}"
-
end
-
-
end
-
1
class FeedbackResponseMap < ResponseMap
-
1
belongs_to :reviewee, :class_name => 'Participant', :foreign_key => 'reviewee_id'
-
1
belongs_to :review, :class_name => 'Response', :foreign_key => 'reviewed_object_id'
-
1
belongs_to :reviewer, :class_name => 'AssignmentParticipant'
-
-
1
def assignment
-
self.review.map.assignment
-
end
-
-
1
def show_review()
-
if self.review
-
return self.review.display_as_html()+"<BR/><BR/><BR/>"
-
else
-
return "<I>No review was performed.</I><BR/><BR/><BR/>"
-
end
-
end
-
-
1
def get_title
-
return "Feedback"
-
end
-
-
1
def questionnaire
-
self.assignment.questionnaires.find_by_type('AuthorFeedbackQuestionnaire')
-
end
-
-
1
def contributor
-
self.review.map.reviewee
-
end
-
end
-
1
class FolderNode < Node
-
1
belongs_to :folder, :class_name => "TreeFolder", :foreign_key => "node_object_id"
-
1
belongs_to :node_object, :class_name => "TreeFolder"
-
-
1
def self.get(sortvar = nil,sortorder =nil,user_id = nil,show = nil,parent_id = nil)
-
13
find(:all, :include => :folder, :conditions => ['type = ? and tree_folders.parent_id is NULL',self.to_s])
-
end
-
-
1
def get_name
-
4357
TreeFolder.find(self.node_object_id).name
-
end
-
-
1
def get_partial_name
-
1950
if self.parent_id.nil?
-
585
return self.get_name.downcase+"_folder_actions"
-
else
-
1365
return "questionnaire_types_actions"
-
end
-
end
-
-
1
def get_child_type
-
651
TreeFolder.find(self.node_object_id).child_type
-
end
-
-
1
def get_children(sortvar = nil,sortorder =nil,user_id = nil,show = nil, parent_id = nil)
-
651
if self.folder.parent_id != nil
-
parent_id = self.folder.id
-
end
-
651
Object.const_get(self.get_child_type).get(sortvar,sortorder,user_id,show,parent_id)
-
end
-
end
-
1
class GlobalSurveyQuestionnaire < Questionnaire
-
1
def after_initialize
-
self.display_type = 'Global Survey'
-
end
-
end
-
1
class ImportError < StandardError
-
end
-
1
class Institution < ActiveRecord::Base
-
1
validates_length_of :name, :minimum => 1
-
1
validates_uniqueness_of :name
-
end
-
-
1
class Instructor < User
-
-
1
QUESTIONNAIRE = [['My questionnaires','list_mine'],
-
['All public questionnaires','list_all']]
-
-
1
SIGNUPSHEET = [['My signups','list_mine'],
-
['All public signups','list_all']]
-
-
1
ASSIGNMENT = [['My assignments','list_mine'],
-
['All public assignments','list_all']]
-
-
1
def list_all(object_type, user_id)
-
object_type.find(:all,
-
:conditions => ["instructor_id = ? OR private = 0", user_id])
-
end
-
-
1
def list_mine(object_type, user_id)
-
object_type.find(:all, :conditions => ["instructor_id = ?", user_id])
-
end
-
-
1
def get(object_type, id, user_id)
-
object_type.find(:first,
-
:conditions => ["id = ? AND (instructor_id = ? OR private = 0)",
-
id, user_id])
-
end
-
end
-
1
class Invitation < ActiveRecord::Base
-
1
belongs_to :to_user, :class_name => "User", :foreign_key => "to_id"
-
1
belongs_to :from_user, :class_name => "User", :foreign_key => "from_id"
-
-
end
-
1
class JoinTeamRequest < ActiveRecord::Base
-
1
belongs_to :team
-
1
has_one :participant
-
end
-
1
class Language < ActiveRecord::Base
-
end
-
1
class LatePolicy < ActiveRecord::Base
-
1
belongs_to :due_date
-
end
-
# Currently this is a repository for a lot of static class methods.
-
# Many of the methods were moved to leaderboard_helper.rb and more
-
# probably should be moved.
-
1
class Leaderboard < ActiveRecord::Base
-
-
# This module is not really required, but can be helpful when
-
# using the script/console and needing to print hash structures.
-
1
require 'pp'
-
-
# This method gets all the assignments associated with a courses
-
# in an array. A course_id of 0 will get assignments not affiliated
-
# with a specific course.
-
-
### This methodreturns unaffiliiated assignments - assignments not affiliated to any course
-
1
def self.getIndependantAssignments(user_id)
-
userAssignments = AssignmentParticipant.find(:all, :conditions =>["user_id = ? ", user_id])
-
noCourseAssignments = Array.new
-
for ua in userAssignments
-
noCA = Assignment.find(:first, :conditions =>["id = ? and course_id is NULL", ua.parent_id])
-
if noCA != nil
-
noCourseAssignments<< noCA
-
end
-
end
-
return noCourseAssignments
-
end
-
-
-
1
def self.getAssignmentsInCourses(courseArray)
-
assignmentList = Assignment.find(:all,
-
:conditions => ["course_id in (?)", courseArray])
-
end
-
-
# This method gets all tuples in the Participants table associated
-
# with a course in the courseArray and puts them into a hash structure
-
# hierarchy (qtype => course => user => score)
-
-
-
-
1
def self.getParticipantEntriesInCourses(courseArray, user_id)
-
assignmentList = getAssignmentsInCourses(courseArray)
-
independantAssignments = getIndependantAssignments(user_id)
-
for iA in independantAssignments
-
assignmentList << iA
-
end
-
questionnaireHash = getParticipantEntriesInAssignmentList(assignmentList)
-
end
-
-
# This method gets all tuples in the Participants table associated
-
# with a specific assignment and puts them into a hash structure
-
# hierarchy (qtype => course => user => score).
-
-
-
1
def self.getParticipantEntriesInAssignment(assignmentID)
-
assignmentList = Array.new
-
assignmentList << Assignment.find(assignmentID)
-
questionnaireHash = getParticipantEntriesInAssignmentList(assignmentList)
-
end
-
-
# This method gets all tuples in the Participants table associated
-
# with an assignment in the assignmentList and puts them into a hash
-
# structure hierarchy (qtype => course => user => score).
-
1
def self.getParticipantEntriesInAssignmentList(assignmentList)
-
-
#Creating an assignment id to course id hash
-
assCourseHash = Hash.new
-
assTeamHash = Hash.new
-
assQuestionnaires = Hash.new
-
-
for assgt in assignmentList
-
-
if assgt.course_id != nil
-
assCourseHash[assgt.id] = assgt.course_id
-
else
-
assCourseHash[assgt.id] = 0
-
end
-
@revqids = []
-
differentQuestionnaires = Hash.new
-
@revqids = AssignmentQuestionnaire.find(:all, :conditions => ["assignment_id = ?",assgt.id])
-
@revqids.each do |rqid|
-
rtype = Questionnaire.find(rqid.questionnaire_id).type
-
if( rtype == 'ReviewQuestionnaire')
-
-
-
differentQuestionnaires["Review"] = rqid.questionnaire_id
-
-
elsif( rtype == 'MetareviewQuestionnaire')
-
-
differentQuestionnaires["Metareview"] = rqid.questionnaire_id
-
elsif( rtype == 'AuthorFeedbackQuestionnaire')
-
differentQuestionnaires["AuthorFeedback"] = rqid.questionnaire_id
-
-
elsif( rtype == 'TeammateReviewQuestionnaire')
-
differentQuestionnaires["Teamreview"] = rqid.questionnaire_id
-
end # end of elsif block
-
end # end of each.do block
-
-
assQuestionnaires[assgt.id] = differentQuestionnaires
-
-
#ACS Everything is a team now
-
#removed check to see if it is a team assignment
-
assTeamHash[assgt.id] = "team"
-
end
-
# end of first for
-
-
-
participantList = AssignmentParticipant.find(:all,
-
:select => "id, user_id, parent_id",
-
:conditions => ["parent_id in (?)", assignmentList])
-
#Creating an participant id to [user id, Assignment id] hash
-
partAssHash = Hash.new
-
for part in participantList
-
partAssHash[part.id] = [part.user_id, part.parent_id]
-
end
-
# csEntries = ComputedScore.find(:all,
-
# :conditions => ["participant_id in (?)", participantList])
-
-
-
csEntries = Array.new
-
#####Computation of csEntries
-
-
-
##The next part of the program expects csEntries to be a array of [participant_id, questionnaire_id, total_score] values
-
## The adaptor class given generates the expected csEntries values using the score_cache table
-
## for all assignments, hadling ,metareviews, feedbacks and teammate reviews, participant_id is the same as reviewee_id, questionnaire_id is the one used for this assignment, and total_score is same as score in the score_cache table
-
## for team assignments, we look up team numbers from the score_cache table, find the participants within the team, for each team member make a new csEntry with the respective participant_id, questionnaire_id, and total_score
-
## code :Abhishek
-
-
-
argList = ['MetareviewResponseMap', 'FeedbackResponseMap','TeammateReviewResponseMap']
-
-
for assgt in assignmentList
-
-
-
-
participants_for_assgt = AssignmentParticipant.find(:all,
-
:conditions =>["parent_id = ? and type =?", assgt.id, 'AssignmentParticipant'])
-
fMTEntries = ScoreCache.find(:all,
-
:conditions =>["reviewee_id in (?) and object_type in (?)", participants_for_assgt, argList])
-
for fMTEntry in fMTEntries
-
csEntry = CsEntriesAdaptor.new
-
csEntry.participant_id = fMTEntry.reviewee_id
-
if (fMTEntry.object_type == 'FeedbackResponseMap')
-
csEntry.questionnaire_id = assQuestionnaires[assgt.id]["AuthorFeedback"]
-
elsif (fMTEntry.object_type == 'MetareviewResponseMap')
-
csEntry.questionnaire_id = assQuestionnaires[assgt.id]["Metareview"]
-
elsif (fMTEntry.object_type == 'TeammateReviewResponseMap')
-
csEntry.questionnaire_id = assQuestionnaires[assgt.id]["Teamreview"]
-
end
-
csEntry.total_score = fMTEntry.score
-
csEntries << csEntry
-
end
-
######## done with metareviews and feedbacksfor this assgt##############
-
##########now putting stuff in reviews based on if the assignment is a team assignment or not###################
-
if assTeamHash[assgt.id] == "indie"
-
participant_entries = ScoreCache.find(:all,
-
:conditions =>["reviewee_id in (?) and object_type = ?", participants_for_assgt, 'ParticipantReviewResponseMap' ])
-
for participant_entry in participant_entries
-
csEntry = CsEntriesAdaptor.new
-
csEntry.participant_id = participant_entry.reviewee_id
-
csEntry.questionnaire_id = assQuestionnaires[assgt.id]["Review"]
-
csEntry.total_score = participant_entry.score
-
csEntries << csEntry
-
end
-
else
-
assignment_teams = Team.find(:all,
-
:conditions => ["parent_id = ? and type = ?", assgt.id, 'AssignmentTeam'])
-
team_entries = ScoreCache.find(:all,
-
:conditions =>["reviewee_id in (?) and object_type = ?", assignment_teams, 'TeamReviewResponseMap'])
-
for team_entry in team_entries
-
team_users = TeamsUser.find(:all,
-
:conditions => ["team_id = ?",team_entry.reviewee_id])
-
-
for team_user in team_users
-
team_participant = AssignmentParticipant.find(:first,
-
:conditions =>["user_id = ? and parent_id = ?", team_user.user_id, assgt.id])
-
csEntry = CsEntriesAdaptor.new
-
csEntry.participant_id = team_participant.id
-
csEntry.questionnaire_id = assQuestionnaires[assgt.id]["Review"]
-
csEntry.total_score = team_entry.score
-
-
csEntries << csEntry
-
end
-
-
end
-
end
-
end
-
#puts "************looking at all the csEntries elements***********"
-
#for csEntry in csEntries
-
#puts "csEntry -> #{csEntry.participant_id} , #{csEntry.questionnaire_id}, #{csEntry.total_score}"
-
#end
-
####################### end of Code Abhishek #############
-
#qtype => course => user => score
-
-
qtypeHash = Hash.new
-
-
-
for csEntry in csEntries
-
-
qtype = Questionnaire.find(csEntry.questionnaire_id).type.to_s
-
courseid = assCourseHash[partAssHash[csEntry.participant_id][1]]
-
userid = partAssHash[csEntry.participant_id][0]
-
-
addEntryToCSHash(qtypeHash, qtype, userid, csEntry, courseid)
-
end
-
-
qtypeHash
-
end
-
-
# This method adds an entry from the Computed_Scores table into a hash
-
# structure that is used to in creating the leaderboards.
-
1
def self.addEntryToCSHash(qtypeHash, qtype, userid, csEntry, courseid)
-
#If there IS NOT any course for the particular course type
-
if qtypeHash[qtype] == nil
-
partHash = Hash.new
-
partHash[userid] = [csEntry.total_score, 1]
-
courseHash = Hash.new
-
courseHash[courseid] = partHash
-
qtypeHash[qtype] = courseHash
-
else
-
#There IS at least one course under the particular qtype
-
#If the particular course IS NOT present in existing course hash
-
if qtypeHash[qtype][courseid] == nil
-
courseHash = qtypeHash[qtype]
-
partHash = Hash.new
-
partHash[userid] = [csEntry.total_score, 1]
-
courseHash[courseid] = partHash
-
qtypeHash[qtype] = courseHash
-
else
-
#The particular course is present
-
#If the particular user IS NOT present in the existing user hash
-
if qtypeHash[qtype][courseid][userid] == nil
-
partHash = qtypeHash[qtype][courseid]
-
partHash[userid] = [csEntry.total_score, 1]
-
qtypeHash[qtype][courseid] = partHash
-
else
-
#User is present, update score
-
current_score = qtypeHash[qtype][courseid][userid][0]
-
count = qtypeHash[qtype][courseid][userid][1]
-
final_score = ((current_score * count) + csEntry.total_score) / (count + 1)
-
count +=(1)
-
qtypeHash[qtype][courseid][userid] = [final_score, count]
-
end
-
end
-
end
-
if qtypeHash[qtype][courseid][userid] == nil
-
partHash[userid] = [csEntry.total_score, 1]
-
courseHash[courseid] = partHash
-
qtypeHash[qtype] = courseHash
-
end
-
end
-
-
# This method does a destructive sort on the computed scores hash so
-
# that it can be mined for personal achievement information
-
1
def self.sortHash(qtypeHash)
-
qtypeHash.each { |qtype, courseHash|
-
courseHash.each { |course, userScoreHash|
-
userScoreSortArray = userScoreHash.sort { |a, b| b[1][0] <=> a[1][0]}
-
qtypeHash[qtype][course] = userScoreSortArray
-
}
-
}
-
qtypeHash
-
end
-
-
-
-
-
-
-
-
-
# This method takes the sorted computed score hash structure and mines
-
# it for personal achievement information.
-
1
def self.extractPersonalAchievements(csHash, courseList, userID)
-
# Get all the possible accomplishments from Leaderboard table
-
-
accompList = Leaderboard.find(:all,
-
:select => 'qtype')
-
# New hash for courses and accomplishments
-
courseAccHash = Hash.new
-
# Go through each course-accomplishment combo
-
courseList.each { |courseID|
-
accompList.each { |accomp|
-
qtypeid = accomp.qtype
-
# Make sure there are no nils in the chain
-
-
if csHash[qtypeid]
-
-
if csHash[qtypeid][courseID]
-
-
-
if csHash[qtypeid][courseID][userID]
-
# We found a combo for accomplishment, course, and user
-
-
if courseAccHash[courseID] == nil
-
courseAccHash[courseID] = Array.new
-
end
-
#puts csHash[qtypeid][courseID][userID].join(",")
-
# Add an array with accomplishment and score
-
courseAccHash[courseID] << [qtypeid, csHash[qtypeid][courseID][userID]]
-
-
-
pp csHash[qtypeid][courseID][userID]
-
end
-
end
-
end
-
}
-
}
-
-
# Next part is to extract ranking from csHash
-
-
# Sort the hash (which changes the structure slightly)
-
# NOTE: This changes the original csHash
-
csSortHash= Leaderboard.sortHash(csHash)
-
-
courseAccomp = Hash.new
-
courseAccHash.each { |courseID, accompScoreArray|
-
# puts "Processing course #{courseID}"
-
accompScoreArray.each { |accompScoreArrayEntry|
-
# pp accompScoreArrayEntry
-
-
# puts accompScoreArrayEntry[courseID][idx]
-
score = accompScoreArrayEntry[1][0]
-
#let me know if you can't understand this part.
-
accomp = accompScoreArrayEntry[0]
-
userScoreArray = accompScoreArrayEntry[1]
-
rank = csSortHash[accomp][courseID].index([userID, userScoreArray])+ 1
-
total = csSortHash[accomp][courseID].length
-
if courseAccomp[courseID] == nil
-
courseAccomp[courseID] = Array.new
-
end
-
courseAccomp[courseID] << { :accomp => Leaderboard.find_by_qtype(accomp).name,
-
:score => score,
-
:rankStr => "#{rank} of #{total}"}
-
}
-
}
-
-
-
courseAccomp
-
-
end
-
-
# Returns string for Top N Leaderboard Heading or accomplishments entry
-
1
def self.leaderboardHeading(qtypeid)
-
ltEntry = Leaderboard.find_by_qtype(qtypeid)
-
if ltEntry
-
ltEntry.name
-
else
-
"No Entry"
-
end
-
end
-
-
end
-
1
class Mailer < ActionMailer::Base
-
1
default from: 'expertiza-support@lists.ncsu.edu'
-
1
default delivery_method: :test if Rails.env.development? || Rails.env.test?
-
-
1
def generic_message(defn)
-
@partial_name = defn[:body][:partial_name]
-
@user = defn[:body][:user]
-
@first_name = defn[:body][:first_name]
-
@password = defn[:body][:password]
-
-
mail(subject: defn[:subject],
-
to: defn[:to],
-
bcc: defn[:bcc])
-
end
-
end
-
1
class MarkupStyle < ActiveRecord::Base
-
1
validates_presence_of :name
-
1
validates_uniqueness_of :name
-
end
-
1
class MenuItem < ActiveRecord::Base
-
-
1
attr_accessor :controller_action, :content_page
-
-
1
validates_presence_of :name
-
1
validates_uniqueness_of :name
-
-
1
def delete
-
children = MenuItem.find(:all, :conditions => ['parent_id = ?',self.id])
-
children.each {|child| child.delete }
-
self.destroy
-
end
-
-
1
def above
-
if self.parent_id
-
conditions =
-
["parent_id = ? and seq = ?", self.parent_id, self.seq - 1]
-
else
-
conditions =
-
["parent_id is null and seq = ?", self.seq - 1]
-
end
-
-
return MenuItem.find(:first,
-
:conditions => conditions)
-
end
-
-
-
1
def below
-
if self.parent_id
-
conditions =
-
["parent_id = ? and seq = ?", self.parent_id, self.seq + 1]
-
else
-
conditions =
-
["parent_id is null and seq = ?", self.seq + 1]
-
end
-
-
return MenuItem.find(:first,
-
:conditions => conditions)
-
end
-
-
-
1
def MenuItem.repack(repack_id)
-
if repack_id
-
items = MenuItem.find(:all,
-
:conditions => "parent_id = #{repack_id}",
-
:order => 'seq')
-
else
-
items = MenuItem.find(:all,
-
:conditions => "parent_id is null",
-
:order => 'seq')
-
end
-
-
seq = 1
-
for item in items do
-
item.seq = seq
-
item.save!
-
seq += 1
-
end
-
end
-
-
-
1
def MenuItem.next_seq(parent_id)
-
if parent_id and parent_id.to_i > 0
-
next_seq = MenuItem.find_by_sql("select coalesce(max(seq) + 1, 1) as seq from menu_items where parent_id = #{parent_id}")
-
else
-
next_seq = MenuItem.find_by_sql("select coalesce(max(seq) + 1, 1) as seq from menu_items where parent_id is null")
-
end
-
-
if next_seq
-
return next_seq[0].seq
-
else
-
return 1
-
end
-
end
-
-
-
1
def MenuItem.items_for_permissions(permission_ids = nil)
-
# Hash for faster & easier lookups
-
23
if permission_ids
-
23
perms = {}
-
23
for id in permission_ids do
-
507
perms[id] = true
-
end
-
end
-
-
# List of items to return
-
23
items = []
-
-
23
menu_items = self.find(:all,
-
:order => 'parent_id, seq, id')
-
23
for item in menu_items do
-
782
if item.controller_action_id.to_i > 0
-
667
item.controller_action =
-
ControllerAction.find(item.controller_action_id)
-
667
if perms
-
667
if perms.has_key?(item.controller_action.effective_permission_id)
-
311
items << item
-
end
-
else
-
items << item
-
end
-
elsif item.content_page_id.to_i > 0
-
115
item.content_page =
-
ContentPage.find(item.content_page_id)
-
115
if perms
-
115
if perms.has_key?(item.content_page.permission_id)
-
71
items << item
-
end
-
else
-
items << item
-
end
-
end
-
end
-
-
23
return items
-
end
-
-
end
-
1
class MetareviewQuestionnaire < Questionnaire
-
1
def after_initialize
-
self.display_type = 'Metareview'
-
end
-
-
1
def symbol
-
return "metareview".to_sym
-
end
-
-
1
def get_assessments_for(participant)
-
participant.get_metareviews()
-
end
-
-
-
end
-
1
class MetareviewResponseMap < ResponseMap
-
1
belongs_to :reviewee, :class_name => 'Participant', :foreign_key => 'reviewee_id'
-
1
belongs_to :review_mapping, :class_name => 'ResponseMap', :foreign_key => 'reviewed_object_id'
-
-
#return all the versions available for a response map.
-
#a person who is doing meta review has to be able to see all the versions of review.
-
1
def get_all_versions()
-
if self.review_mapping.response
-
@sorted_array=Array.new
-
@prev=Response.all
-
for element in @prev
-
if(element.map_id==self.review_mapping.id)
-
array_not_empty=1
-
@sorted_array << element
-
end
-
end
-
@sorted=@sorted_array.sort { |m1,m2|(m1.version_num and m2.version_num) ? m1.version_num <=> m2.version_num : (m1.version_num ? -1 : 1)}
-
#return all the lists in ascending order.
-
return @sorted
-
else
-
return nil #"<I>No review was performed.</I><br/><hr/><br/>"
-
end
-
end
-
-
1
def contributor
-
self.review_mapping.reviewee
-
end
-
-
1
def questionnaire
-
self.assignment.questionnaires.find_by_type('MetareviewQuestionnaire')
-
end
-
-
1
def review_questionnaire
-
self.assignment.questionnaires.find_by_type("ReviewQuestionnaire")
-
end
-
-
1
def get_title
-
return "Metareview"
-
end
-
-
1
def assignment
-
self.review_mapping.assignment
-
end
-
-
1
def self.export(csv,parent_id,options)
-
mappings = Assignment.find(parent_id).metareview_mappings
-
mappings = mappings.sort_by{|a| [a.review_mapping.reviewee.name,a.reviewee.name,a.reviewer.name]}
-
mappings.each{
-
|map|
-
csv << [
-
map.review_mapping.reviewee.name,
-
map.reviewee.name,
-
map.reviewer.name
-
]
-
}
-
end
-
-
1
def self.get_export_fields(options)
-
fields = ["contributor","reviewed by","metareviewed by"]
-
return fields
-
end
-
-
1
def self.import(row,session,id)
-
if row.length < 3
-
raise ArgumentError.new("Not enough items. The string should contain: Author, Reviewer, ReviewOfReviewer1 <, ..., ReviewerOfReviewerN>")
-
end
-
-
index = 2
-
while index < row.length
-
#ACS Make All contributors as teams
-
contributor = AssignmentTeam.find_by_name_and_parent_id(row[0].to_s.strip, id)
-
-
if contributor == nil
-
raise ImportError, "Contributor, "+row[0].to_s+", was not found."
-
end
-
-
ruser = User.find_by_name(row[1].to_s.strip)
-
reviewee = AssignmentParticipant.find_by_user_id_and_parent_id(ruser.id, id)
-
if reviewee.nil?
-
raise ImportError, "Reviewee, "+row[1].to_s+", for contributor, "+contributor.name+", was not found."
-
end
-
-
muser = User.find_by_name(row[index].to_s.strip)
-
reviewer = AssignmentParticipant.find_by_user_id_and_parent_id(muser.id, id)
-
if reviewer.nil?
-
raise ImportError, "Metareviewer, "+row[index].to_s+", for contributor, "+contributor.name+", and reviewee, "+row[1].to_s+", was not found."
-
end
-
-
#ACS Removed the if condition(and corressponding else) which differentiate assignments as team and individual assignments
-
# to treat all assignments as team assignments
-
reviewmapping = TeamReviewResponseMap.find_by_reviewee_id_and_reviewer_id(contributor.id, reviewee.id)
-
if reviewmapping.nil?
-
raise ImportError, "No review mapping was found for contributor, "+contributor.name+", and reviewee, "+row[1].to_s+"."
-
end
-
-
existing_mappings = MetareviewResponseMap.find_all_by_reviewee_id_and_reviewer_id_and_reviewed_object_id(reviewee.id, reviewer.id, reviewmapping.id)
-
# if no mappings have already been imported for this combination
-
# create it.
-
-
if existing_mappings.size == 0
-
MetareviewResponseMap.create(:reviewer_id => reviewer.id, :reviewee_id => reviewee.id, :reviewed_object_id => reviewmapping.id )
-
end
-
-
index += 1
-
end
-
end
-
end
-
# This is one type of Questionnaire and as intuitively expected this model class
-
# derives from Questionnaire.
-
-
# This implements Metasurvey(type) specific model methods.We implement the metasurvey
-
# specific functionality of associating the current metasurvey to "selected" surveys.
-
-
# These methods are invoked when called by any activeRecord object(row) of
-
# questionnaires table with type 'Metasurvey'
-
-
1
class Metasurvey < Questionnaire
-
# for doc on why we do it this way,
-
# see http://blog.hasmanythrough.com/2007/1/15/basic-rails-association-cardinality
-
-
# can these be inherited too?
-
1
validates_presence_of :name
-
1
validates_numericality_of :max_question_score
-
1
validates_numericality_of :min_question_score
-
-
1
def specific_edit (role,instructor)
-
@surveys = Survey.find_by_sql "select * from Questionnaires where type='Survey' AND (#{role} > (select r.id from roles r, users u where r.id=u.role_id and instructor_id = u.id) OR private=0 OR instructor_id = #{instructor} )"
-
@surveys
-
end
-
-
1
def update_mapping(questionnaire_id,selected)
-
@rubric = Metasurvey.find(questionnaire_id)
-
selected.each do |select|
-
@sur= Questionnaire.find_by_name(select)
-
@sur.survey_mapping_id=questionnaire_id;
-
@sur.save
-
end
-
end
-
end
-
1
class MissingObjectIDError < StandardError
-
1
def exception
-
"No object ID was provided to the import process. Please contact the system administrator. Model Name: Course"
-
end
-
end
-
#Base Node class
-
#Provides common method definitions, but minimal functoinality.
-
#Must be subclassed for use in tree_display code
-
#
-
#Author: AJBUDLON
-
#Date: 7/18/2008
-
1
class Node < ActiveRecord::Base
-
1
acts_as_nested_set
-
-
1
belongs_to :parent, :class_name => 'Node', :foreign_key => 'parent_id'
-
-
# Retrieves the nodes of this type
-
1
def self.get(sortvar = nil,sortorder =nil,user_id = nil,show = nil, parent_id = nil)
-
end
-
-
# Retrieves the children of this node
-
1
def get_children(sortvar = nil,sortorder =nil,user_id = nil,show = nil,parent_id = nil)
-
end
-
-
# Retrieves the action partial for this node
-
1
def get_partial_name
-
108
self.class.table+"_actions"
-
end
-
-
# Most objects are not leaves
-
# Currently only assignment and questionnaire are a leaf
-
# type node
-
1
def is_leaf
-
650
false
-
end
-
-
# Retrieves the corresponding model for the
-
# node's object type
-
1
def self.table
-
end
-
-
# Retreives the node's object name
-
1
def get_name
-
end
-
-
# Retrieves the node's object directory
-
1
def get_directory
-
end
-
-
# Retrieves the node's object create_at
-
1
def get_creation_date
-
end
-
-
# Retrieves the type of children this node has
-
1
def get_child_type
-
end
-
end
-
1
class Participant < ActiveRecord::Base
-
1
belongs_to :user
-
1
belongs_to :topic, :class_name => 'SignUpTopic'
-
1
belongs_to :assignment, :foreign_key => 'parent_id'
-
-
1
has_many :comments, :dependent => :destroy
-
1
has_many :resubmission_times, :dependent => :destroy
-
1
has_many :reviews, :class_name => 'ResponseMap', :foreign_key => 'reviewer_id'
-
1
has_many :team_reviews, :class_name => 'TeamReviewResponseMap', :foreign_key => 'reviewer_id'
-
1
has_many :response_maps, :class_name =>'ResponseMap', :foreign_key => 'reviewee_id'
-
-
1
validates_numericality_of :grade, :allow_nil => true
-
-
1
def review_response_maps
-
ParticipantReviewResponseMap.find_all_by_reviewee_id_and_reviewed_object_id(id, assignment.id)
-
end
-
-
1
def get_current_stage
-
assignment.try :get_current_stage, topic_id
-
end
-
1
alias_method :current_stage, :get_current_stage
-
-
1
def get_stage_deadline
-
assignment.get_stage_deadline topic_id
-
end
-
1
alias_method :stage_deadline, :get_stage_deadline
-
-
1
def name
-
User.find(self.user_id).name
-
end
-
-
1
def fullname
-
User.find(self.user_id).fullname
-
end
-
-
1
def delete(force = nil)
-
maps = ResponseMap.find(:all, :conditions => ['reviewee_id = ? or reviewer_id = ?',self.id,self.id])
-
-
if force or ((maps.nil? or maps.length == 0) and
-
self.team.nil?)
-
force_delete(maps)
-
else
-
raise "Associations exist for this participant"
-
end
-
end
-
-
1
def force_delete(maps)
-
times = ResubmissionTime.find(:all, :conditions => ['participant_id = ?',self.id])
-
-
if times
-
times.each { |time| time.destroy }
-
end
-
-
if maps
-
maps.each { |map| map.delete(true) }
-
end
-
-
if self.team
-
if self.team.teams_users.length == 1
-
self.team.delete
-
else
-
self.team.teams_users.each{ |tuser|
-
if tuser.user_id == self.id
-
tuser.delete
-
end
-
}
-
end
-
end
-
self.destroy
-
end
-
-
1
def get_topic_string
-
if topic.nil? or topic.topic_name.empty?
-
return "<center>—</center>"
-
end
-
return topic.topic_name
-
end
-
-
1
def able_to_submit
-
if submit_allowed
-
return true
-
end
-
return false
-
end
-
-
1
def able_to_review
-
if review_allowed
-
return true
-
end
-
return false
-
end
-
-
1
def email(pw, home_page)
-
user = User.find_by_id(self.user_id)
-
assignment = Assignment.find_by_id(self.assignment_id)
-
-
Mailer.deliver_message(
-
{:recipients => user.email,
-
:subject => "You have been registered as a participant in Assignment #{assignment.name}",
-
:body => {
-
:home_page => home_page,
-
:first_name => ApplicationHelper::get_user_first_name(user),
-
:name =>user.name,
-
:password =>pw,
-
:partial_name => "register"
-
}
-
}
-
)
-
end
-
-
#This function updates the topic_id for a participant in assignments where a signup sheet exists
-
#If the assignment is not a team assignment then this method should be called on the object of the participant
-
#If the assignment is a team assignment then this method should be called on the participant object of one of the team members.
-
#Other team members records will be updated automatically.
-
1
def update_topic_id(topic_id)
-
assignment = Assignment.find(self.parent_id)
-
-
#ACS Call the select method for all the teams(single or group)
-
#removed check to see if it is a team assignment
-
team = Team.find_by_sql("SELECT u.team_id as team_id
-
FROM teams as t,teams_users as u
-
WHERE t.parent_id = " + assignment.id.to_s + " and t.id = u.team_id and u.user_id = " + self.user_id.to_s )
-
-
team_id = team[0]["team_id"]
-
team_members = TeamsUser.find_all_by_team_id(team_id)
-
-
team_members.each { |team_member|
-
participant = Participant.find_by_user_id_and_parent_id(team_member.user_id,assignment.id)
-
participant.update_attribute(:topic_id, topic_id)
-
}
-
end
-
-
# Returns the average score of all reviews for this user on this assignment (Which assignment ??? )
-
1
def get_average_score()
-
return 0 if self.response_maps.size == 0
-
-
sum_of_scores = 0
-
-
self.response_maps.each do |response_map|
-
if !response_map.response.nil? then
-
sum_of_scores = sum_of_scores + response_map.response.get_average_score
-
end
-
end
-
-
(sum_of_scores / self.response_maps.size).to_i
-
end
-
-
1
def get_average_score_per_assignment(assignment_id)
-
return 0 if self.response_maps.size == 0
-
-
sum_of_scores = 0
-
-
self.response_maps.metareview_response_maps.each do |metaresponse_map|
-
if !metaresponse_map.response.nil? && response_map == assignment_id then
-
sum_of_scores = sum_of_scores + response_map.response.get_average_score
-
end
-
end
-
-
(sum_of_scores / self.response_maps.size).to_i
-
end
-
-
# Returns the average score of one question from all reviews for this user on this assignment as an floating point number
-
# Params: question - The Question object to retrieve the scores from
-
1
def get_average_question_score(question)
-
sum_of_scores = 0
-
number_of_scores = 0
-
-
self.response_maps.each do |response_map|
-
# TODO There must be a more elegant way of doing this...
-
unless response_map.response.nil?
-
response_map.response.scores.each do |score|
-
if score.question == question then
-
sum_of_scores = sum_of_scores + score.score
-
number_of_scores = number_of_scores + 1
-
end
-
end
-
end
-
end
-
-
return 0 if number_of_scores == 0
-
(((sum_of_scores.to_f / number_of_scores.to_f) * 100).to_i) / 100.0
-
end
-
-
# Return scores that this participant for the given questions
-
1
def get_scores(questions)
-
scores = Hash.new
-
scores[:participant] = self
-
self.assignment.questionnaires.each do |questionnaire|
-
scores[questionnaire.symbol] = Hash.new
-
scores[questionnaire.symbol][:assessments] = questionnaire.get_assessments_for(self)
-
-
scores[questionnaire.symbol][:scores] = Score.compute_scores(scores[questionnaire.symbol][:assessments], questions[questionnaire.symbol])
-
end
-
scores[:total_score] = assignment.compute_total_score(scores)
-
return scores
-
end
-
end
-
1
class ParticipantReviewResponseMap < ReviewResponseMap
-
1
belongs_to :reviewee, :class_name => 'Participant', :foreign_key => 'reviewee_id'
-
1
belongs_to :contributor, :class_name => 'Participant', :foreign_key => 'reviewee_id'
-
-
end
-
1
class PathError < StandardError
-
end
-
1
class Permission < ActiveRecord::Base
-
-
1
validates_presence_of :name
-
1
validates_uniqueness_of :name
-
-
1
has_many :content_pages
-
1
has_many :controller_actions
-
-
# Find Permissions for a Role ID or an array of Role IDs.
-
-
1
def Permission.find_for_role(role_ids)
-
31
return find_by_sql( ["select permissions.* from permissions inner join roles_permissions on permissions.id = roles_permissions.permission_id where role_id in (?) order by permissions.name", role_ids] )
-
end
-
-
-
# Find all Permissions for a Role. This method gets the hierarchy
-
# for the given Role and uses that to get all the Permissions for
-
# the Role and its ancestors.
-
-
1
def Permission.find_all_for_role(role)
-
roles = Role.hierarchy(role.id)
-
return find_for_role(roles)
-
end
-
-
-
# Find Permissions that are not already associated with the given
-
# Role ID.
-
-
1
def Permission.find_not_for_role(role_id)
-
return find_by_sql( ["select * from permissions where id not in (select permission_id from roles_permissions where role_id in (?)) order by name", role_id] )
-
end
-
-
end
-
1
class Question < ActiveRecord::Base
-
1
belongs_to :questionnaire # each question belongs to a specific questionnaire
-
1
belongs_to :review_score # each review_score pertains to a particular question
-
1
belongs_to :review_of_review_score # ditto
-
1
has_many :question_advices, :order => 'score' # for each question, there is separate advice about each possible score
-
1
has_many :signup_choices # ?? this may reference signup type questionnaires
-
1
has_one :question_type
-
-
1
validates_presence_of :txt # user must define text content for a question
-
1
validates_presence_of :weight # user must specify a weight for a question
-
1
validates_numericality_of :weight # the weight must be numeric
-
-
# Class variables
-
# Class variables
-
1
NUMERIC = 'Numeric' # Display string for NUMERIC questions
-
1
TRUE_FALSE = 'True/False' # Display string for TRUE_FALSE questions
-
1
GRADING_TYPES = [[NUMERIC,false],[TRUE_FALSE,true]]
-
-
-
1
CHECKBOX = 'Checkbox' # Display string for NUMERIC questions
-
1
TEXT_FIELD = 'TextField'
-
1
TEXTAREA = 'TextArea' # Display string for TRUE_FALSE questions
-
1
DROPDOWN = 'DropDown'
-
1
UPLOAD_FILE = 'UploadFile'
-
1
RATING = 'Rating'
-
-
1
GRADING_TYPES_CUSTOM = [[CHECKBOX,0],[TEXT_FIELD,1],[TEXTAREA,2],[DROPDOWN,3],[UPLOAD_FILE, 4],[RATING, 5]]
-
1
WEIGHTS = [['1',1],['2',2],['3',3],['4',4],['5',5]]
-
-
1
attr_accessor :checked
-
-
1
def delete
-
QuestionAdvice.find_all_by_question_id(self.id).each{|advice| advice.destroy}
-
self.destroy
-
end
-
end
-
1
class QuestionAdvice < ActiveRecord::Base
-
1
belongs_to :question, :dependent => :destroy
-
end
-
1
class QuestionType < ActiveRecord::Base
-
-
1
belongs_to :question
-
-
1
validates_presence_of :q_type # user must define type for the custom question
-
end
-
1
class Questionnaire < ActiveRecord::Base
-
-
1
def get_weighted_score(assignment, scores)
-
return compute_weighted_score(self.symbol, assignment, scores)
-
end
-
-
# for doc on why we do it this way,
-
# see http://blog.hasmanythrough.com/2007/1/15/basic-rails-association-cardinality
-
1
has_many :questions # the collection of questions associated with this Questionnaire
-
1
belongs_to :instructor, :class_name => "User", :foreign_key => "instructor_id" # the creator of this questionnaire
-
-
1
has_many :assignment_questionnaires, :class_name => 'AssignmentQuestionnaire', :foreign_key => 'questionnaire_id'
-
1
has_many :assignments, :through => :assignment_questionnaires
-
-
1
validates_presence_of :name
-
1
validates_numericality_of :max_question_score
-
1
validates_numericality_of :min_question_score
-
-
1
validates_presence_of :section, :on => :create # indicates custom rubric section
-
-
1
DEFAULT_MIN_QUESTION_SCORE = 0 # The lowest score that a reviewer can assign to any questionnaire question
-
1
DEFAULT_MAX_QUESTION_SCORE = 5 # The highest score that a reviewer can assign to any questionnaire question
-
1
DEFAULT_QUESTIONNAIRE_URL = "http://www.courses.ncsu.edu/csc517"
-
-
1
def compute_weighted_score(symbol, assignment, scores)
-
aq = self.assignment_questionnaires.find_by_assignment_id(assignment.id)
-
if scores[symbol][:scores][:avg]
-
#dont bracket and to_f the whole thing - you get a 0 in the result.. what you do is just to_f the 100 part .. to get the fractions
-
-
return scores[symbol][:scores][:avg] * aq.questionnaire_weight / 100.to_f
-
else
-
return 0
-
end
-
end
-
-
# Does this questionnaire contain true/false questions?
-
1
def true_false_questions?
-
for question in questions
-
if question.true_false
-
return true
-
end
-
end
-
-
return false
-
end
-
-
1
def delete
-
self.assignments.each{
-
| assignment |
-
raise "The assignment #{assignment.name} uses this questionnaire. Do you want to <A href='../assignment/delete/#{assignment.id}'>delete</A> the assignment?"
-
}
-
-
self.questions.each{
-
| question |
-
question.delete
-
}
-
-
-
node = QuestionnaireNode.find_by_node_object_id(self.id)
-
if node
-
node.destroy
-
end
-
-
self.destroy
-
end
-
-
-
1
def max_possible_score
-
results = Questionnaire.find_by_sql("SELECT (SUM(q.weight)*rs.max_question_score) as max_score FROM questions q, questionnaires rs WHERE q.questionnaire_id = rs.id AND rs.id = #{self.id}")
-
return results[0].max_score
-
end
-
-
# validate the entries for this questionnaire
-
1
def validate
-
3
if max_question_score < 1
-
errors.add(:max_question_score, "The maximum question score must be a positive integer.")
-
end
-
3
if min_question_score >= max_question_score
-
errors.add(:min_question_score, "The minimum question score must be less than the maximum")
-
end
-
-
3
results = Questionnaire.find(:all,
-
:conditions => ["id <> ? and name = ? and instructor_id = ?",
-
id, name, instructor_id])
-
3
errors.add(:name, "Questionnaire names must be unique.") if results != nil and results.length > 0
-
end
-
end
-
1
class QuestionnaireNode < Node
-
1
belongs_to :questionnaire, :class_name => "Questionnaire", :foreign_key => "node_object_id"
-
1
belongs_to :node_object, :class_name => "Questionnaire"
-
-
1
def self.table
-
108
"questionnaires"
-
end
-
-
1
def self.get(sortvar = nil,sortorder = nil, user_id = nil,show = nil,parent_id = nil)
-
456
if show
-
456
if User.find(user_id).role.name != "Teaching Assistant"
-
456
conditions = 'questionnaires.instructor_id = ?'
-
else
-
conditions = 'questionnaires.instructor_id in (?)'
-
end
-
else
-
if User.find(user_id).role.name != "Teaching Assistant"
-
conditions = '(questionnaires.private = 0 or questionnaires.instructor_id = ?)'
-
else
-
conditions = '(questionnaires.private = 0 or questionnaires.instructor_id in (?))'
-
end
-
end
-
-
456
if User.find(user_id).role.name != "Teaching Assistant"
-
456
values = user_id
-
else
-
values = Ta.get_mapped_instructor_ids(user_id)
-
end
-
-
456
if parent_id
-
name = TreeFolder.find(parent_id).name+"Questionnaire"
-
name.gsub!(/[^\w]/,'')
-
conditions += " and questionnaires.type = \"#{name}\""
-
end
-
-
456
if sortvar.nil? or sortvar == 'directory_path'
-
sortvar = 'name'
-
end
-
456
if sortorder.nil?
-
sortorder = 'ASC'
-
end
-
-
456
find(:all, :include => :questionnaire, :conditions => [conditions,values], :order => "questionnaires.#{sortvar} #{sortorder}")
-
end
-
-
1
def get_name
-
72
Questionnaire.find(self.node_object_id).name
-
end
-
-
1
def get_creation_date
-
72
Questionnaire.find(self.node_object_id).created_at
-
end
-
-
# Gets the updated_at from the associated Questionnaire
-
1
def get_modified_date
-
Questionnaire.find(self.node_object_id).updated_at
-
end
-
-
1
def is_leaf
-
36
true
-
end
-
end
-
1
class QuestionnaireTypeNode < FolderNode
-
1
belongs_to :table, :class_name => "TreeFolder", :foreign_key => "node_object_id"
-
1
belongs_to :node_object, :class_name => "TreeFolder"
-
-
1
def self.table
-
"tree_folders"
-
end
-
-
1
def self.get(sortvar = nil,sortorder =nil,user_id = nil,show = nil,parent_id = nil)
-
65
parent = TreeFolder.find_by_name("Questionnaires")
-
65
folders = TreeFolder.find_all_by_parent_id(parent.id)
-
65
nodes = Array.new
-
65
folders.each{
-
| folder |
-
node = FolderNode.find_by_node_object_id(folder.id)
-
if node != nil
-
nodes << node
-
end
-
}
-
65
return nodes
-
end
-
-
1
def get_partial_name
-
"questionnaire_type_actions"
-
end
-
-
1
def get_name
-
TreeFolder.find(self.node_object_id).name
-
end
-
-
1
def get_children(sortvar = nil,sortorder = nil,user_id = nil,show=nil,parent_id = nil)
-
QuestionnaireNode.get(sortvar,sortorder,user_id,show,self.node_object_id)
-
end
-
end
-
1
class Response < ActiveRecord::Base
-
1
belongs_to :map, :class_name => 'ResponseMap', :foreign_key => 'map_id'
-
1
has_many :scores, :class_name => 'Score', :foreign_key => 'response_id', :dependent => :destroy
-
-
1
delegate :questionnaire, :reviewee, :reviewer,
-
:to => :map
-
-
1
def team_has_user?(user)
-
reviewer.team.has_user user
-
end
-
-
1
def display_as_html(prefix = nil, count = nil, file_url = nil)
-
identifier = ""
-
# The following three lines print out the type of rubric before displaying
-
# feedback. Currently this is only done if the rubric is Author Feedback.
-
# It doesn't seem necessary to print out the rubric type in the case of
-
# a ReviewResponseMap. Also, I'm not sure if that would have to be
-
# TeamResponseMap for a team assignment. Someone who understands the
-
# situation better could add to the code later.
-
if self.map.type.to_s == 'FeedbackResponseMap'
-
identifier += "<H2>Feedback from author</H2>"
-
end
-
if prefix
-
identifier += "<B>Reviewer:</B> #{count}"#+self.map.reviewer.fullname
-
str = prefix+"_"+self.id.to_s
-
else
-
identifier += '<B>'+self.map.get_title+'</B> '+count.to_s+'</B>'
-
str = self.id.to_s
-
end
-
code = identifier+' <a href="#" name= "review_'+str+'Link" onClick="toggleElement('+"'review_"+str+"','review'"+');return false;">hide review</a><BR/>'
-
code += "<B>Last reviewed:</B> "
-
if self.updated_at.nil?
-
code += "Not available"
-
else
-
code += self.updated_at.strftime('%A %B %d %Y, %I:%M%p')
-
end
-
code += '<div id="review_'+str+'" style=""><BR/><BR/>'
-
-
# Test for whether custom rubric needs to be used
-
if ((self.map.questionnaire.section.eql? "Custom") && (self.map.type.to_s != 'FeedbackResponseMap'))
-
#return top of view
-
return code
-
end
-
# End of custom code
-
count = 0
-
self.scores.each {
-
|reviewScore|
-
count += 1
-
code += '<big><b>Question '+count.to_s+":</b> <I>"+Question.find_by_id(reviewScore.question_id).txt+"</I></big><BR/><BR/>"
-
code += '<TABLE CELLPADDING="5"><TR><TD valign="top"><B>Score:</B></TD><TD><FONT style="BACKGROUND-COLOR:gold">'+reviewScore.score.to_s+"</FONT> out of <B>"+Question.find_by_id(reviewScore.question_id).questionnaire.max_question_score.to_s+"</B></TD></TR>"
-
if reviewScore.comments != nil
-
code += '<TR><TD valign="top"><B>Response:</B></TD><TD>' + reviewScore.comments.gsub("<", "<").gsub(">", ">").gsub(/\n/, '<BR/>')
-
end
-
code += '</TD></TR></TABLE><BR/>'
-
}
-
-
if self.additional_comment != nil
-
comment = self.additional_comment.gsub('^p', '').gsub(/\n/, '<BR/> ')
-
else
-
comment = ''
-
end
-
code += "<B>Additional Comment:</B><BR/>"+comment+"</div>"
-
return code.html_safe
-
end
-
-
# Computes the total score awarded for a review
-
1
def get_total_score
-
scores.map(&:score).sum
-
end
-
-
#Generate an email to the instructor when a new review exceeds the allowed difference
-
#ajbudlon, nov 18, 2008
-
1
def notify_on_difference(new_pct, avg_pct, limit)
-
mapping = self.map
-
instructor = mapping.assignment.instructor
-
Mailer.deliver_message(
-
{:recipients => instructor.email,
-
:subject => "Expertiza Notification: A review score is outside the acceptable range",
-
:body => {
-
:first_name => ApplicationHelper::get_user_first_name(instructor),
-
:reviewer_name => mapping.reviewer.fullname,
-
:type => "review",
-
:reviewee_name => mapping.reviewee.fullname,
-
:limit => limit,
-
:new_pct => new_pct,
-
:avg_pct => avg_pct,
-
:types => "reviews",
-
:performer => "reviewer",
-
:assignment => mapping.assignment,
-
:partial_name => 'limit_notify'
-
}
-
}
-
)
-
end
-
-
1
def delete
-
self.scores.each { |score| score.destroy }
-
self.destroy
-
end
-
-
#bug fixed
-
# Returns the average score for this response as an integer (0-100)
-
1
def get_average_score()
-
if get_maximum_score != 0 then
-
((get_total_score.to_f / get_maximum_score.to_f) * 100).to_i
-
else
-
0
-
end
-
end
-
-
# Returns the maximum possible score for this response
-
1
def get_maximum_score()
-
max_score = 0
-
-
self.scores.each { |score| max_score = max_score + score.question.questionnaire.max_question_score }
-
-
max_score
-
end
-
-
# Returns the total score from this response
-
1
def get_alternative_total_score()
-
# TODO The method get_total_score() above does not seem correct. Replace with this method.
-
total_score = 0
-
-
self.scores.each { |score| total_score = total_score + score.score }
-
-
total_score
-
end
-
-
# Function which considers a given assignment
-
# and checks if a given review is still valid for score calculation
-
# The basic rule is that
-
# "A review is INVALID if there was new submission for the assignment
-
# before the most recent review deadline AND THE review happened before that
-
# submission"
-
# response - the response whose validity is being checked
-
# resubmission_times - submission times of the assignment is descending order
-
# latest_review_phase_start_time
-
# The function returns true if a review is valid for score calculation
-
# and false otherwise
-
1
def is_valid_for_score_calculation?(resubmission_times, latest_review_phase_start_time)
-
is_valid = true
-
-
# if there was not submission then the response is valid
-
if resubmission_times.nil? || latest_review_phase_start_time.nil?
-
return is_valid
-
end
-
-
resubmission_times.each do |resubmission_time|
-
# if the response is after a resubmission that is
-
# before the latest_review_phase_start_time (check second condition below)
-
# then we are good - the response is valid and we can break
-
if (self.updated_at > resubmission_time.resubmitted_at)
-
break
-
end
-
-
# this means there was a re-submission before the
-
# latest_review_phase_start_time and we dont have a response after that
-
# so the response is invalid
-
if (resubmission_time.resubmitted_at < latest_review_phase_start_time)
-
is_valid = false
-
break
-
end
-
end
-
-
is_valid
-
end
-
-
1
require 'analytic/response_analytic'
-
1
include ResponseAnalytic
-
end
-
1
class ResponseMap < ActiveRecord::Base
-
1
belongs_to :reviewer, :class_name => 'Participant', :foreign_key => 'reviewer_id'
-
1
has_one :response, :class_name => 'Response', :foreign_key => 'map_id'
-
1
has_many :metareview_response_maps, :class_name => 'MetareviewResponseMap', :foreign_key => 'reviewed_object_id'
-
1
has_many :metareview_responses, :source => :responses, :finder_sql => 'SELECT meta.* FROM responses r, response_maps meta, response_maps rev WHERE r.map_id = m.id AND m.type = \'MetaeviewResponseMap\' AND m.reviewee_id = p.id AND p.id = #{id}'
-
-
# return latest versions of the responses
-
1
def self.get_assessments_for(participant)
-
responses = Array.new
-
-
if participant
-
@array_sort=Array.new
-
@sort_to=Array.new
-
-
#get all the versions
-
maps = find(:all, :conditions => ['reviewee_id = ? and type = ?',participant.id,self.to_s])
-
maps.each{ |map|
-
if map.response
-
@all_resp=Response.all
-
for element in @all_resp
-
if(element.map_id==map.id)
-
@array_sort << element
-
end
-
end
-
#sort all versions in descending order and get the latest one.
-
@sort_to=@array_sort.sort { |m1,m2|(m1.version_num and m2.version_num) ? m2.version_num <=> m1.version_num : (m1.version_num ? -1 : 1)}
-
responses << @sort_to[0]
-
@array_sort.clear
-
@sort_to.clear
-
end
-
}
-
#responses = Response.find(:all, :include => :map, :conditions => ['reviewee_id = ? and type = ?',participant.id, self.to_s])
-
responses.sort! {|a,b| a.map.reviewer.fullname <=> b.map.reviewer.fullname }
-
end
-
return responses
-
end
-
-
# return latest versions of the response given by reviewer
-
1
def self.get_reviewer_assessments_for(participant, reviewer)
-
map = ResponseMap.find(:all, :conditions => ['reviewee_id = ? and reviewer_id = ? and type = ?', participant.id, reviewer.id, self.to_s])
-
return Response.find_all_by_map_id(map).sort { |m1,m2|(m1.version_num and m2.version_num) ? m2.version_num <=> m1.version_num : (m1.version_num ? -1 : 1)}[0]
-
end
-
-
# Placeholder method, override in derived classes if required.
-
1
def get_all_versions()
-
return []
-
end
-
-
1
def delete(force = nil)
-
if self.response != nil and !force
-
raise "A response exists for this mapping."
-
elsif self.response != nil
-
self.response.delete
-
end
-
self.destroy
-
end
-
-
1
def show_review()
-
return nil
-
end
-
-
1
def show_feedback()
-
return nil
-
end
-
-
# Evaluates whether this response_map was metareviewed by metareviewer
-
# @param[in] metareviewer AssignmentParticipant object
-
1
def metareviewed_by?(metareviewer)
-
return MetareviewResponseMap.count(:conditions => ['reviewee_id = ? AND reviewer_id = ? AND reviewed_object_id = ?',
-
reviewer.id, metareviewer.id, self.id]) > 0
-
end
-
-
# Assigns a metareviewer to this review (response)
-
# @param[in] metareviewer AssignmentParticipant object
-
1
def assign_metareviewer(metareviewer)
-
MetareviewResponseMap.create(:reviewed_object_id => self.id,
-
:reviewer_id => metareviewer.id, :reviewee_id => reviewer.id)
-
end
-
-
1
def self.delete_mappings(mappings, force=nil)
-
failedCount = 0
-
mappings.each{
-
|mapping|
-
assignment_id = mapping.assignment.id
-
begin
-
mapping.delete(force)
-
rescue
-
failedCount += 1
-
end
-
}
-
return failedCount
-
end
-
-
end
-
1
class ResubmissionTime < ActiveRecord::Base
-
end
-
1
class ReviewComment < ActiveRecord::Base
-
#associate the comment with the file
-
1
belongs_to :review_files, :class_name => 'ReviewFile',
-
:foreign_key => 'review_file_id'
-
end
-
1
class ReviewFile < ActiveRecord::Base
-
# Associate the author (participant) with the file
-
1
belongs_to :participant, :class_name => 'Participant',
-
:foreign_key => 'author_participant_id'
-
-
# Associate the review_comments with the review_file
-
1
has_many :review_comments, :class_name => 'ReviewComment',
-
:foreign_key => 'review_file_id'
-
-
-
#attr_accessor :filepath, :author_participant_id, :version_number
-
-
# Returns the version_number of the collectively most recent version of code
-
# review files submitted by participant (and all members by the team if any)
-
1
def self.get_max_version_num(participant)
-
# Find the max version number of code submitted by 'participant'
-
file = ReviewFile.find(
-
:first, :conditions => ['author_participant_id = ?', participant.id],
-
:order => 'version_number desc')
-
#if file
-
# max_version_num = file.version_number
-
#else
-
# max_version_num = 0
-
#end
-
max_version_num = file.nil? ? 0 : file.version_number
-
-
-
# For all other members of the team, find the most recent version of code
-
# review files submitted by any of them.
-
if participant.assignment.team_assignment?
-
participant.team.get_participants.each { |member|
-
file = ReviewFile.find(
-
:first, :conditions => ['author_participant_id = ?', member.id],
-
:order => 'version_number desc')
-
-
#if file
-
# max_member_version = file.version_number
-
#else
-
# max_member_version = 0
-
#end
-
-
max_member_version = file.nil? ? 0 : file.version_number
-
-
max_version_num = max_member_version if max_member_version > max_version_num
-
}
-
end
-
puts max_version_num
-
return max_version_num
-
end
-
-
-
# Returns row in the ReviewFile table that has a filepath equal to one
-
# computed by the concatenation of this method's arguments.
-
1
def self.get_file(code_review_dir, version_number, base_file_name)
-
filepath = code_review_dir + ReviewFilesHelper::VERSION_DIR_SUFFIX +
-
version_number.to_s + '//' + base_file_name
-
ReviewFile.find_by_filepath(filepath)
-
end
-
-
-
-
end
-
1
class ReviewQuestionnaire < Questionnaire
-
1
def after_initialize
-
283
self.display_type = 'Review'
-
end
-
-
1
def symbol
-
return "review".to_sym
-
end
-
-
1
def get_assessments_for(participant)
-
participant.get_reviews()
-
end
-
-
-
end
-
1
class ReviewResponseMap < ResponseMap
-
1
belongs_to :assignment, :class_name => 'Assignment', :foreign_key => 'reviewed_object_id'
-
-
1
def questionnaire
-
self.assignment.questionnaires.find_by_type('ReviewQuestionnaire')
-
end
-
-
1
def get_title
-
return "Review"
-
end
-
-
1
def delete(force = nil)
-
if self.response != nil and !force
-
raise "A response exists for this mapping."
-
elsif self.response != nil
-
fmaps = FeedbackResponseMap.find_all_by_reviewed_object_id(self.response.id)
-
fmaps.each{|fmap| fmap.delete(true)}
-
self.response.delete
-
end
-
maps = MetareviewResponseMap.find_all_by_reviewed_object_id(self.id)
-
maps.each{|map| map.delete(force)}
-
self.destroy
-
end
-
-
1
def self.get_export_fields(options)
-
fields = ["contributor","reviewed by"]
-
return fields
-
end
-
-
1
def self.export(csv,parent_id,options)
-
mappings = find(:all, :conditions => ['reviewed_object_id=?',parent_id])
-
mappings.sort!{|a,b| a.reviewee.name <=> b.reviewee.name}
-
mappings.each{
-
|map|
-
csv << [
-
map.reviewee.name,
-
map.reviewer.name
-
]
-
}
-
end
-
-
1
def self.import(row,session,id)
-
if row.length < 2
-
raise ArgumentError, "Not enough items"
-
end
-
-
assignment = Assignment.find(id)
-
if assignment.nil?
-
raise ImportError, "The assignment with id \"#{id}\" was not found. <a href='/assignment/new'>Create</a> this assignment?"
-
end
-
index = 1
-
while index < row.length
-
user = User.find_by_name(row[index].to_s.strip)
-
if user.nil?
-
raise ImportError, "The user account for the reviewer \"#{row[index]}\" was not found. <a href='/users/new'>Create</a> this user?"
-
end
-
reviewer = AssignmentParticipant.find_by_user_id_and_parent_id(user.id,assignment.id)
-
if reviewer == nil
-
raise ImportError, "The reviewer \"#{row[index]}\" is not a participant in this assignment. <a href='/users/new'>Register</a> this user as a participant?"
-
end
-
#ACS the reviewee is always a team member
-
#removed code that treated individual and team assignments differently
-
reviewee = AssignmentTeam.find_by_name_and_parent_id(row[0].to_s.strip, assignment.id)
-
if reviewee == nil
-
raise ImportError, "The author \"#{row[0].to_s.strip}\" was not found. <a href='/users/new'>Create</a> this user?"
-
end
-
existing = TeamReviewResponseMap.find_by_reviewee_id_and_reviewer_id(reviewee.id, reviewer.id)
-
if existing.nil?
-
TeamReviewResponseMap.create(:reviewer_id => reviewer.id, :reviewee_id => reviewee.id, :reviewed_object_id => assignment.id)
-
end
-
index += 1
-
end
-
end
-
-
1
def show_feedback()
-
if self.response
-
map = FeedbackResponseMap.find_by_reviewed_object_id(self.response.id)
-
if map and map.response
-
return "<br/><hr/><br/>"+map.response.display_as_html()
-
end
-
else
-
return nil
-
end
-
end
-
-
# This method adds a new entry in the ResponseMap
-
1
def self.add_reviewer(contributor_id, reviewer_id, assignment_id)
-
if find(:first, :conditions => ['reviewee_id = ? and reviewer_id = ?', contributor_id, reviewer_id]).nil?
-
create(:reviewee_id => contributor_id,
-
:reviewer_id => reviewer_id,
-
:reviewed_object_id => assignment_id)
-
else
-
raise "The reviewer, \""+reviewer.name+"\", is already assigned to this contributor."
-
end
-
end
-
-
end
-
1
class RolesPermission < ActiveRecord::Base
-
-
1
def RolesPermission.find_for_role(role_ids)
-
return find_by_sql [%q{
-
select roles_permissions.*, permissions.name
-
from roles_permissions inner join permissions
-
on roles_permissions.permission_id = permissions.id
-
where role_id in (?) order by permissions.name
-
4
}, role_ids]
-
end
-
-
end
-
# This is one type of Questionnaire and as intuitively expected this model class
-
# derives from Questionnaire.
-
-
# This implements Rubric(type) specific model methods ( Rubric does not have any type specific
-
# functionality). These methods are invoked when called by any activeRecord object(row) of
-
# questionnaires table with type 'Rubric'
-
-
1
class Rubric < Questionnaire
-
# for doc on why we do it this way,
-
# see http://blog.hasmanythrough.com/2007/1/15/basic-rails-association-cardinality
-
-
# can these be inherited too?
-
1
validates_presence_of :name
-
1
validates_numericality_of :max_question_score
-
1
validates_numericality_of :min_question_score
-
-
1
def update_mapping
-
redirect_to :action => 'list' ,:type_id=> type_id
-
end
-
-
end
-
1
class Score < ActiveRecord::Base
-
1
belongs_to :question
-
-
# Computes the total score for a list of assessments
-
# parameters
-
# assessments - a list of assessments of some type (e.g., author feedback, teammate review)
-
# questions - the list of questions that was filled out in the process of doing those assessments
-
1
def self.compute_scores(assessments, questions)
-
scores = Hash.new
-
if assessments.length > 0
-
scores[:max] = -999999999
-
scores[:min] = 999999999
-
total_score = 0
-
length_of_assessments=assessments.length.to_f
-
q_types = Array.new
-
questions.each {
-
|question|
-
q_types << QuestionType.find_by_question_id(question.id)
-
}
-
assessments.each {
-
|assessment|
-
#questionnaire = Questionnaire.find(assessment.)
-
-
curr_score = get_total_score(:response => assessment, :questions => questions, :q_types => q_types)
-
-
if curr_score > scores[:max]
-
scores[:max] = curr_score
-
end
-
if curr_score < scores[:min]
-
scores[:min] = curr_score
-
end
-
-
# Check if the review is invalid. If is not valid do not include in score calculation
-
if @invalid==1
-
length_of_assessments=length_of_assessments-1
-
curr_score=0
-
end
-
total_score += curr_score
-
}
-
if (length_of_assessments!=0)
-
scores[:avg] = total_score.to_f / length_of_assessments
-
else
-
scores[:avg]=0
-
end
-
else
-
scores[:max] = nil
-
scores[:min] = nil
-
scores[:avg] = nil
-
end
-
return scores
-
end
-
-
# Computes the total score for an assessment
-
# params
-
# assessment - specifies the assessment for which the total score is being calculated
-
# questions - specifies the list of questions being evaluated in the assessment
-
-
1
def self.get_total_score(params)
-
@response = params[:response]
-
@questions = params[:questions]
-
@q_types = params[:q_types]
-
-
weighted_score = 0
-
sum_of_weights = 0
-
@invalid=0
-
#Check for invalid reviews.
-
#Check if the latest review done by the reviewer falls into the latest review stage
-
map=ResponseMap.find(@response.map_id)
-
-
@questionnaire = Questionnaire.find(@questions[0].questionnaire_id)
-
-
x = 0
-
if @questionnaire.section == "Custom"
-
@questions.each {
-
|question|
-
item = Score.find_by_response_id_and_question_id(@response.id, question.id)
-
if @q_types.length <= x
-
@q_types[x] = QuestionType.find_by_question_id(question.id)
-
end
-
-
if @q_types[x].q_type == "Rating"
-
ratingPart = @q_types[x].parameters.split("::").last
-
if ratingPart.split("|")[0] == "1"
-
if (!item.nil?)
-
weighted_score += item.comments.to_i * question.weight
-
sum_of_weights += question.weight
-
end
-
end
-
end
-
x = x + 1
-
}
-
else
-
@questions.each {
-
|question|
-
item = Score.find_by_response_id_and_question_id(@response.id, question.id)
-
if item != nil
-
weighted_score += item.score * question.weight
-
end
-
sum_of_weights += question.weight
-
}
-
end
-
-
#assignment_participant = Participant.find(:all, :conditions => ["id = ?", map.reviewee_id])
-
-
due_dates = DueDate.find(:all, :conditions => ["assignment_id = ?", map.reviewed_object_id])
-
-
# to check the validity of the response
-
if due_dates.size!=0
-
@sorted_deadlines=Array.new
-
@sorted_deadlines=due_dates.sort { |m1, m2| (m1.due_at and m2.due_at) ? m2.due_at <=> m1.due_at : (m1.due_at ? -1 : 1) }
-
-
#find the latest review deadline
-
#less than current time
-
flag = 0
-
latest_review_phase_start_time = nil
-
current_time = Time.new
-
for deadline in @sorted_deadlines
-
# if flag is set then we saw a review deadline in the
-
# previous iteration - check if this deadline is a past
-
# deadline
-
if ((flag == 1) && (deadline.due_at <= current_time))
-
latest_review_phase_start_time = deadline.due_at
-
break
-
else
-
flag = 0
-
end
-
-
# we found a review or re-review deadline - examine the next deadline
-
# to check if it is past
-
if (deadline.deadline_type_id == 4 ||deadline.deadline_type_id == 2)
-
flag = 1
-
end
-
end
-
-
resubmission_times = ResubmissionTime.find(:all, :conditions => ["participant_id = ?", map.reviewee_id], :order => "resubmitted_at DESC")
-
-
if @response.is_valid_for_score_calculation?(resubmission_times, latest_review_phase_start_time)
-
@invalid = 0
-
else
-
@invalid = 1
-
end
-
-
#if(@response.created_at < next_ele.due_at)
-
# @invalid=0
-
#else
-
# @invalid = 1
-
#end
-
end
-
-
if (sum_of_weights > 0)
-
return (weighted_score.to_f / (sum_of_weights.to_f * @questionnaire.max_question_score.to_f)) * 100
-
else
-
return -1 #indicating no score
-
end
-
end
-
-
1
require 'analytic/score_analytic'
-
1
include ScoreAnalytic
-
end
-
1
class ScoreCache < ActiveRecord::Base
-
-
## makes an entry into score_cache table whenever a response is given/edited.
-
## handles team and individual assignments differently - for individual assignments the reviewee_id = participant.id, for team assignments, reviewee_id = team_id
-
1
def self.update_cache(rid)
-
@ass_id = 0
-
@userset = []
-
@team = 0
-
@team_number = 0
-
@teamass = 0
-
@reviewmap = Response.find(rid).map_id #find the map_id for this review
-
@rm = ResponseMap.find(@reviewmap) #find the map for this review
-
@participant1 = AssignmentParticipant.new
-
@contributor_id = 0
-
@map_type = @rm.type.to_s #find type of Response map
-
@t_score = 0
-
@t_min = 0
-
@teammember = TeamsUser.new
-
@t_max = 0
-
-
if @map_type == "TeamReviewResponseMap"
-
get_team_score()
-
else
-
get_participant_score()
-
end
-
update_score_cache()
-
#########################
-
end
-
-
1
def self.get_team_score()
-
@ass_id = @rm.reviewed_object_id
-
@assignment1 = Assignment.find(@ass_id)
-
@teammember = TeamsUser.find(:first, :conditions => ["team_id = ?",@rm.reviewee_id]) #team which is being reviewed
-
@participant1 = AssignmentParticipant.find(:first, :conditions =>["user_id = ? and parent_id = ?", @teammember.user_id, @ass_id])
-
@contributor_id = @teammember.team_id
-
@questions = Hash.new
-
questionnaires = @assignment1.questionnaires
-
questionnaires.each{
-
|questionnaire|
-
@questions[questionnaire.symbol] = questionnaire.questions
-
}
-
team = Team.find(@contributor_id)
-
@allscores = team.get_scores(@questions)
-
end
-
-
1
def self.get_participant_score()
-
@participant1 = AssignmentParticipant.find(@rm.reviewee_id) # entire tuple with info of asgnment n participant
-
@contributor_id = @participant1.id
-
@assignment1 = Assignment.find(@participant1.parent_id)
-
@ass_id = @assignment1.id
-
@questions = Hash.new
-
questionnaires = @assignment1.questionnaires
-
questionnaires.each{
-
|questionnaire|
-
@questions[questionnaire.symbol] = questionnaire.questions
-
}
-
@allscores = @participant1.get_scores( @questions) # Return scores that this participant has given
-
end
-
-
1
def self.update_score_cache()
-
@p_score = 0
-
@p_min = 0
-
@p_max = 0
-
@scorehash = get_score_set_for_review_type(@allscores, @map_type) ##isolates the scores for the particular item needed
-
-
@p_score = @scorehash[:avg]
-
@p_min = @scorehash[:min]
-
@p_max = @scorehash[:max]
-
-
sc = ScoreCache.find(:first,:conditions =>["reviewee_id = ? and object_type = ?", @contributor_id, @map_type ])
-
if sc == nil
-
@msgs = "first entry"
-
sc = ScoreCache.new
-
sc.reviewee_id = @contributor_id
-
range_string = ((@p_min*100).round/100.0).to_s + "-" + ((@p_max*100).round/100.0).to_s
-
sc.range = range_string
-
sc.score = (@p_score*100).round/100.0
-
sc.object_type = @map_type
-
sc.save
-
# make another new tuple for new score
-
else
-
range_string = ((@p_min*100).round/100.0).to_s + "-" + ((@p_max*100).round/100.0).to_s
-
sc.range = range_string
-
sc.score = (@p_score*100).round/100.0
-
#presenceflag = 2
-
sc.save
-
#look for a consolidated score and change
-
end
-
end
-
-
1
def self.get_score_set_for_review_type(allscores, map_type)
-
##isolates the scores for the particular item needed (eg: Review, MetaReview, Feedback etc)
-
# ParticipantReviewResponseMap - Review mappings for single user assignments
-
# TeamReviewResponseMap - Review mappings for team based assignments
-
# MetareviewResponseMap - Metareview mappings
-
# TeammateReviewResponseMap - Review mapping between teammates
-
# FeedbackResponseMap - Feedback from author to reviewer
-
-
score_set = Hash.new
-
if map_type == "ParticipantReviewResponseMap"
-
if allscores[:review]
-
score_set = compute_scoreset(allscores , "review")
-
end
-
elsif map_type == "TeamReviewResponseMap"
-
if allscores[:review]
-
score_set = compute_scoreset(allscores , "review")
-
end
-
-
elsif map_type == "TeammateReviewResponseMap"
-
if allscores[:review]
-
score_set = compute_scoreset(allscores , "teammate")
-
end
-
-
elsif map_type == "MetareviewResponseMap"
-
if allscores[:metareview]
-
score_set = compute_scoreset(allscores , "metareview")
-
end
-
elsif map_type == "FeedbackResponseMap"
-
if allscores[:feedback]
-
score_set = compute_scoreset(allscores , "feedback")
-
end
-
end
-
@scoreset = Hash.new
-
@scoreset[:avg] = score_set[:avg]
-
@scoreset[:min] = score_set[:min]
-
@scoreset[:max] = score_set[:max]
-
return @scoreset
-
end
-
-
1
def self.compute_scoreset(allscores , score_param)
-
score_stat = Hash.new
-
if score_param != nil && allscores[score_param.to_sym] != nil
-
score_parameter = score_param.to_sym
-
score_stat[:avg] = allscores[score_parameter][:scores][:avg]
-
score_stat[:min] = allscores[score_parameter][:scores][:min]
-
score_stat[:max] = allscores[score_parameter][:scores][:max]
-
else
-
score_stat[:avg] = nil
-
score_stat[:min] = nil
-
score_stat[:max] = nil
-
end
-
return score_stat
-
end
-
end
-
1
class SignUpTopic < ActiveRecord::Base
-
1
has_many :signed_up_users, :foreign_key => 'topic_id', :dependent => :destroy
-
1
has_many :topic_dependencies, :foreign_key => 'topic_id', :dependent => :destroy
-
1
has_many :topic_deadlines, :foreign_key => 'topic_id', :dependent => :destroy
-
1
alias_method :deadlines, :topic_deadlines
-
1
has_many :assignment_participants, :foreign_key => 'topic_id'
-
-
1
belongs_to :assignment
-
-
#the below relations have been added to make it consistent with the database schema
-
1
validates_presence_of :topic_name, :assignment_id, :max_choosers
-
1
validates_length_of :topic_identifier, :maximum => 10
-
-
#This method is not used anywhere
-
#def get_team_id_from_topic_id(user_id)
-
# return find_by_sql("select t.id from teams t,teams_users u where t.id=u.team_id and u.user_id = 5");
-
#end
-
-
1
def self.import(row,session,id = nil)
-
-
if row.length != 4
-
raise ArgumentError, "CSV File expects the format: Topic identifier, Topic name, Max choosers, Topic Category"
-
end
-
-
topic = SignUpTopic.find_by_topic_name_and_assignment_id(row[1],session[:assignment_id])
-
-
if topic == nil
-
attributes = ImportTopicsHelper::define_attributes(row)
-
ImportTopicsHelper::create_new_sign_up_topic(attributes,session)
-
else
-
topic.max_choosers = row[2]
-
topic.topic_identifier = row[0]
-
#topic.assignment_id = session[:assignment_id]
-
topic.save
-
end
-
end
-
-
1
def self.find_slots_filled(assignment_id)
-
#SignUpTopic.find_by_sql("SELECT topic_id as topic_id, COUNT(t.max_choosers) as count FROM sign_up_topics t JOIN signed_up_users u ON t.id = u.topic_id WHERE t.assignment_id =" + assignment_id+ " and u.is_waitlisted = false GROUP BY t.id")
-
SignUpTopic.find_by_sql(["SELECT topic_id as topic_id, COUNT(t.max_choosers) as count FROM sign_up_topics t JOIN signed_up_users u ON t.id = u.topic_id WHERE t.assignment_id = ? and u.is_waitlisted = false GROUP BY t.id", assignment_id])
-
end
-
-
1
def self.find_slots_waitlisted(assignment_id)
-
#SignUpTopic.find_by_sql("SELECT topic_id as topic_id, COUNT(t.max_choosers) as count FROM sign_up_topics t JOIN signed_up_users u ON t.id = u.topic_id WHERE t.assignment_id =" + assignment_id + " and u.is_waitlisted = true GROUP BY t.id")
-
SignUpTopic.find_by_sql(["SELECT topic_id as topic_id, COUNT(t.max_choosers) as count FROM sign_up_topics t JOIN signed_up_users u ON t.id = u.topic_id WHERE t.assignment_id = ? and u.is_waitlisted = true GROUP BY t.id", assignment_id])
-
end
-
-
1
def self.find_waitlisted_topics(assignment_id,creator_id)
-
#SignedUpUser.find_by_sql("SELECT u.id FROM sign_up_topics t, signed_up_users u WHERE t.id = u.topic_id and u.is_waitlisted = true and t.assignment_id = " + assignment_id.to_s + " and u.creator_id = " + creator_id.to_s)
-
SignedUpUser.find_by_sql(["SELECT u.id FROM sign_up_topics t, signed_up_users u WHERE t.id = u.topic_id and u.is_waitlisted = true and t.assignment_id = ? and u.creator_id = ?", assignment_id.to_s, creator_id.to_s])
-
end
-
-
1
def self.slotAvailable?(topic_id)
-
topic = SignUpTopic.find(topic_id)
-
no_of_students_who_selected_the_topic = SignedUpUser.find_all_by_topic_id_and_is_waitlisted(topic_id, false)
-
-
if !no_of_students_who_selected_the_topic.nil?
-
if topic.max_choosers > no_of_students_who_selected_the_topic.size
-
return true
-
else
-
return false
-
end
-
else
-
return true
-
end
-
end
-
-
-
1
def self.cancel_all_waitlists(creator_id, assignment_id)
-
waitlisted_topics = SignUpTopic.find_waitlisted_topics(assignment_id,creator_id)
-
if !waitlisted_topics.nil?
-
for waitlisted_topic in waitlisted_topics
-
entry = SignedUpUser.find(waitlisted_topic.id)
-
entry.destroy
-
end
-
end
-
-
end
-
-
1
def update_waitlisted_users(max_choosers)
-
num_of_users_promotable = max_choosers.to_i - self.max_choosers.to_i
-
-
num_of_users_promotable.times {
-
next_wait_listed_user = SignedUpUser.find(:first, :conditions => {:topic_id => self.id, :is_waitlisted => true})
-
if !next_wait_listed_user.nil?
-
next_wait_listed_user.is_waitlisted = false
-
next_wait_listed_user.save
-
-
#update participants
-
assignment = Assignment.find(self.assignment_id)
-
-
if assignment.team_assignment?
-
user_id = TeamsUser.find(:first, :conditions => {:team_id => next_wait_listed_user.creator_id}).user_id
-
participant = Participant.find_by_user_id_and_parent_id(user_id,assignment.id)
-
else
-
participant = Participant.find_by_user_id_and_parent_id(next_wait_listed_user.creator_id,assignment.id)
-
end
-
-
participant.update_topic_id(self.id)
-
end
-
}
-
end
-
end
-
1
class SignedUpUser < ActiveRecord::Base
-
1
belongs_to :topic, :class_name => 'SignUpTopic'
-
-
#the below has been added to make is consistent with the database schema
-
1
validates_presence_of :topic_id, :creator_id
-
#This method is not used anywhere
-
#def cancel_waitlists_of_users(creator_id, assignment_id)
-
# waitlisted_topics = SignedUpUser.find_by_sql("SELECT u.id FROM sign_up_topics t, signed_up_users u WHERE t.id = u.topic_id and u.is_waitlisted = true and t.assignment_id = " + assignment_id.to_s + " and u.creator_id = " + creator_id.to_s)
-
# SignedUpUser
-
# if !waitlisted_topics.nil?
-
# for waitlisted_topic in waitlisted_topics
-
# entry = SignedUpUser.find(waitlisted_topic.id)
-
# entry.destroy
-
# end
-
# end
-
-
#end
-
-
1
def self.find_team_participants(assignment_id)
-
#@participants = SignedUpUser.find_by_sql("SELECT s.id as id, t.id as topic_id, t.topic_name as name , s.is_waitlisted as is_waitlisted, s.creator_id, s.creator_id as team_id FROM signed_up_users s, sign_up_topics t where s.topic_id = t.id and t.assignment_id = " + assignment_id)
-
@participants = SignedUpUser.find_by_sql(["SELECT s.id as id, t.id as topic_id, t.topic_name as name , s.is_waitlisted as is_waitlisted, s.creator_id, s.creator_id as team_id FROM signed_up_users s, sign_up_topics t where s.topic_id = t.id and t.assignment_id = ? ",assignment_id])
-
i=0
-
for participant in @participants
-
#participant_names = SignedUpUser.find_by_sql("SELECT s.name as u_name, t.name as team_name FROM users s, teams t, teams_users u WHERE t.id = u.team_id and u.user_id = s.id and t.id = " + participant.team_id)
-
participant_names = SignedUpUser.find_by_sql(["SELECT s.name as u_name, t.name as team_name FROM users s, teams t, teams_users u WHERE t.id = u.team_id and u.user_id = s.id and t.id = ?", participant.team_id])
-
team_name_added = false
-
names = '(missing team)'
-
for participant_name in participant_names
-
if team_name_added == false
-
names = "<br/> <b>" + participant_name.team_name + "</b>" + "<br/>" + participant_name.u_name + " "
-
team_name_added = true
-
else
-
names = names + participant_name.u_name + " "
-
end
-
end
-
@participants[i].name = names
-
i = i + 1
-
end
-
@participants
-
end
-
-
1
def self.find_participants(assignment_id)
-
#SignedUpUser.find_by_sql("SELECT t.id as topic_id,u.name as name, s.is_waitlisted as is_waitlisted FROM signed_up_users s, users u, sign_up_topics t where s.creator_id = u.id and s.topic_id = t.id and t.assignment_id = " + assignment_id)
-
SignedUpUser.find_by_sql(["SELECT t.id as topic_id,u.name as name, s.is_waitlisted as is_waitlisted FROM signed_up_users s, users u, sign_up_topics t where s.creator_id = u.id and s.topic_id = t.id and t.assignment_id = ?", assignment_id])
-
end
-
-
1
def self.find_team_users(assignment_id,user_id)
-
#TeamsUser.find_by_sql("SELECT t.id as t_id FROM teams_users u, teams t WHERE u.team_id = t.id and t.parent_id =" + assignment_id.to_s + " and user_id =" + user_id.to_s)
-
TeamsUser.find_by_sql(["SELECT t.id as t_id FROM teams_users u, teams t WHERE u.team_id = t.id and t.parent_id = ? and user_id = ?", assignment_id.to_s, user_id.to_s])
-
end
-
-
1
def self.find_user_signup_topics(assignment_id,creator_id)
-
#SignedUpUser.find_by_sql("SELECT t.id as topic_id, t.topic_name as topic_name, u.is_waitlisted as is_waitlisted FROM sign_up_topics t, signed_up_users u WHERE t.id = u.topic_id and t.assignment_id = " + assignment_id.to_s + " and u.creator_id =" + creator_id.to_s)
-
SignedUpUser.find_by_sql(["SELECT t.id as topic_id, t.topic_name as topic_name, u.is_waitlisted as is_waitlisted FROM sign_up_topics t, signed_up_users u WHERE t.id = u.topic_id and t.assignment_id = ? and u.creator_id = ?", assignment_id.to_s, creator_id.to_s])
-
end
-
-
#This method is not used anywhere
-
#def self.find_team_members_fullname(team_id)
-
# TeamsUser.find_by_sql("SELECT s.fullname as fullname, u.team_id as t_id FROM teams_users u, users s WHERE u.team_id = " + team_id + " and s.id = u.user_id")
-
#end
-
-
#This method is not used anywhere
-
#def self.find_team_members_name(team_id)
-
# TeamsUser.find_by_sql("SELECT s.name as u_name FROM teams_users u, users s WHERE u.team_id = " + team_id + " and s.id = u.user_id")
-
#end
-
-
#This method is not used anywhere
-
#def self.find_invitation_senders_team(assignment_id,user_id)
-
# TeamsUser.find_by_sql("SELECT t.id as t_id FROM teams_users u, teams t WHERE u.team_id = t.id and t.parent_id =" + assignment_id.to_s + " and user_id =" + user_id.to_s)
-
#end
-
-
-
end
-
1
class SignupResubmissionQuota < ActiveRecord::Base
-
end
-
1
class SiteController < ActiveRecord::Base
-
1
has_many :controller_actions
-
1
belongs_to :permission
-
-
1
validates_presence_of :name
-
1
validates_uniqueness_of :name
-
-
1
scope :builtin, -> { where(builtin: 1).order(:name) }
-
1
scope :application, -> { where('builtin is null or builtin = 0').order(:name) }
-
-
1
def actions
-
@actions ||= controller_actions.order(:name)
-
end
-
-
-
1
def self.classes
-
classes = Hash.new
-
-
ObjectSpace.each_object(Class) do |klass|
-
if klass.respond_to?(:controller_name) && klass.superclass.to_s == ApplicationController.to_s
-
classes[klass.controller_name] = klass
-
end
-
end
-
-
classes
-
end
-
end
-
-
1
class Student < User
-
1
def get_home_action
-
"list"
-
end
-
-
1
def get_home_controller
-
return "student_task"
-
end
-
end
-
# Author: Andrew Kofink, 2013-09-28
-
1
class StudentTask
-
1
attr_accessor :assignment, :current_stage, :participant, :stage_deadline, :topic
-
-
1
def initialize(args)
-
@assignment = args[:assignment]
-
@current_stage = args[:current_stage]
-
@participant = args[:participant]
-
@stage_deadline = args[:stage_deadline]
-
@topic = args[:topic]
-
end
-
-
1
def self.from_participant(participant)
-
StudentTask.new(
-
:participant => participant,
-
:assignment => participant.assignment,
-
:topic => participant.topic,
-
:current_stage => participant.current_stage,
-
:stage_deadline => (Time.parse(participant.stage_deadline) rescue Time.now + 1.years)
-
)
-
end
-
-
1
def self.from_participant_id(id)
-
from_participant AssignmentParticipant.find(id)
-
end
-
-
1
def self.from_user(user)
-
user.assignment_participants.map do |participant|
-
StudentTask.from_participant participant
-
end.sort_by(&:stage_deadline)
-
end
-
-
1
def topic_name
-
topic.try(:topic_name) || '-'
-
end
-
-
1
def complete?
-
stage_deadline == 'Complete'
-
end
-
-
1
def content_submitted_in_current_stage?
-
(current_stage == "submission" || current_stage == "resubmission") &&
-
(participant.resubmission_times.size > 0 || hyperlinks.present?)
-
end
-
-
1
def course
-
assignment.course
-
end
-
-
1
def hyperlinks
-
@hyperlinks ||= participant.get_hyperlinks
-
end
-
-
1
def incomplete?
-
!complete?
-
end
-
-
1
def metareviews_given?
-
response_maps.inject(nil) { |i, j| i || (j.response && j.class.to_s[/Metareview/]) }
-
end
-
-
1
def metareviews_given_in_current_stage?
-
current_stage == 'metareview' && metareviews_given?
-
end
-
-
1
def metareview_notification_accepted?
-
response_maps.inject(nil) { |i, j| i || j.class.to_s[/Metareview/] && j.notification_accepted }
-
end
-
-
1
def not_started?
-
in_work_stage? && !started?
-
end
-
-
1
def notify?
-
reviews_given_in_current_stage? && !review_notification_accepted? ||
-
metareviews_given_in_current_stage? && !metareview_notification_accepted?
-
end
-
-
1
include ActionView::Helpers::DateHelper
-
1
def relative_deadline
-
time_ago_in_words(stage_deadline) if stage_deadline
-
end
-
-
1
def response_maps
-
participant.response_maps
-
end
-
-
1
def review_notification_accepted?
-
response_maps.inject(nil) { |i, j| i || j.class.to_s[/Review/] && j.notification_accepted }
-
end
-
-
1
def reviews_given?
-
response_maps.inject(nil) { |i, j| i || (j.response && j.class.to_s[/Review/]) }
-
end
-
-
1
def reviews_given_in_current_stage?
-
current_stage == 'review' || current_stage == 'rereview' && reviews_given?
-
end
-
-
1
def in_work_stage?
-
current_stage == 'submission' ||
-
current_stage == 'resubmission' ||
-
current_stage == 'review' ||
-
current_stage == 'rereview' ||
-
current_stage == 'metareview'
-
end
-
-
1
def revision?
-
content_submitted_in_current_stage? ||
-
reviews_given_in_current_stage? ||
-
metareviews_given_in_current_stage?
-
end
-
-
1
def started?
-
@started ||= incomplete? &&
-
(content_submitted_in_current_stage? ||
-
reviews_given_in_current_stage? ||
-
metareviews_given_in_current_stage?)
-
end
-
-
1
def topic
-
participant.topic
-
end
-
end
-
1
class Suggestion < ActiveRecord::Base
-
1
validates_presence_of :title, :description
-
1
has_many :suggestion_comments
-
-
1
def find_all_by_assignment_id(assignment_id)
-
find(:all, :conditions => ["assignment_id = ?", assignment_id])
-
end
-
end
-
1
class SuggestionComment < ActiveRecord::Base
-
1
validates_presence_of :comments
-
1
belongs_to :suggestion
-
end
-
-
1
class SuperAdministrator < User
-
-
1
QUESTIONNAIRE = [["My instructor's questionnaires",'list_instructors'],
-
["My admin's questionnaires",'list_admins'],
-
["My questionnaires",'list_mine'],
-
['All public questionnaires','list_all'],
-
['All private questionnaires','list_all_private']]
-
-
1
SIGNUPSHEET = [["My instructor's signups",'list_instructors'],
-
["My admin's signups",'list_admins'],
-
['My signups','list_mine'],
-
['All public signups','list_all'],
-
['All private signups','list_all_private']]
-
-
1
ASSIGNMENT = [["My instructor's assignments",'list_instructors'],
-
["My admin's assignments",'list_admins'],
-
['My assignments','list_mine'],
-
['All public assignments','list_all'],
-
['All private assignments','list_all_private']]
-
-
1
def get(object_type, id, user_id)
-
object_type.find(:first, :conditions => ["id = ?", id])
-
end
-
-
1
def list_all(object_type, user_id)
-
object_type.find(:all, :conditions => "private = 0")
-
end
-
-
1
def list_all_private(object_type, user_id)
-
object_type.find(:all, :conditions => "private = 1")
-
end
-
-
1
def list_admins(object_type, user_id)
-
if (object_type != SignupSheet)
-
object_type.find(:all,
-
:joins => "inner join users on " + object_type.to_s.pluralize + ".instructor_id = users.id AND users.parent_id = " + user_id.to_s)
-
else
-
object_type.find(:all,
-
:joins => "inner join users on instructor_id = users.id AND users.parent_id = " + user_id.to_s)
-
end
-
end
-
-
1
def list_instructors(object_type, user_id)
-
if (object_type != SignupSheet)
-
object_type.find(:all,
-
:joins => "inner join users on " + object_type.to_s.pluralize + ".instructor_id = users.id AND users.parent_id = " + user_id.to_s)
-
else
-
object_type.find(:all,
-
:joins => "inner join users on instructor_id = users.id AND users.parent_id = " + user_id.to_s)
-
end
-
end
-
-
1
def get(object_type, id, user_id)
-
object_type.find(:first,
-
:conditions => ["id = ?", id])
-
end
-
end
-
1
class SurveyDeployment < ActiveRecord::Base
-
1
validates_numericality_of :num_of_students
-
1
validates_presence_of :num_of_students
-
1
validates_presence_of :start_date
-
1
validates_presence_of :end_date
-
-
1
def validate
-
if((end_date != nil) && (start_date != nil) && (end_date-start_date)<0)
-
errors.add_to_base("End Date should be in the future of Start Date.")
-
end
-
if((start_date != nil) && start_date<Time.now)
-
errors.add_to_base("Start Date should be in the future.")
-
end
-
if((end_date != nil) && end_date<Time.now)
-
errors.add_to_base("End Date should be in the future.")
-
end
-
-
if(num_of_students!=nil && num_of_students > User.find_all_by_role_id(Role.student.id).length)
-
errors.add(:num_of_students," - Too many students. #{num_of_students} : #{User.find_all_by_role_id(Role.student.id).length}")
-
end
-
-
-
end
-
-
end
-
1
class SurveyParticipant < ActiveRecord::Base
-
end
-
1
class SurveyQuestionnaire < Questionnaire
-
1
def after_initialize
-
self.display_type = 'Survey'
-
end
-
end
-
1
class SurveyResponse < ActiveRecord::Base
-
1
belongs_to :assignment
-
1
belongs_to :questionnaire
-
1
belongs_to :question
-
-
end
-
1
class SystemSettings < ActiveRecord::Base
-
1
set_table_name 'system_settings'
-
-
1
attr_accessor :public_role, :default_markup_style
-
1
attr_accessor :site_default_page, :not_found_page, :permission_denied_page,
-
:session_expired_page
-
-
1
def public_role
-
@public_role ||= Role.find(self.public_role_id)
-
end
-
-
1
def default_markup_style
-
if not @default_markup_style
-
if self.default_markup_style_id
-
@default_markup_style = MarkupStyle.find(self.default_markup_style_id)
-
else
-
@default_markup_style = MarkupStyle.new(:id => nil,
-
:name => '(None)')
-
end
-
end
-
return @default_markup_style
-
end
-
-
1
def site_default_page
-
@site_default_page ||= ContentPage.find(self.site_default_page_id)
-
end
-
-
1
def not_found_page
-
@not_found_page ||= ContentPage.find(self.not_found_page_id)
-
end
-
-
1
def permission_denied_page
-
@permission_denied_page ||= ContentPage.find(self.permission_denied_page_id)
-
end
-
-
1
def session_expired_page
-
@session_expired_page ||= ContentPage.find(self.session_expired_page_id)
-
end
-
-
# Returns an array of system page settings for a given page,
-
# or nil if the page is not a system page.
-
1
def system_pages(pageid)
-
pages = Array.new
-
-
if self.site_default_page_id == pageid
-
pages << "Site default page"
-
end
-
if self.not_found_page_id == pageid
-
pages << "Not found page"
-
end
-
if self.permission_denied_page_id == pageid
-
pages << "Permission denied page"
-
end
-
if self.session_expired_page_id == pageid
-
pages << "Session expired page"
-
end
-
-
if pages.length > 0
-
return pages
-
else
-
return nil
-
end
-
end
-
-
end
-
-
1
class Ta < User
-
1
has_many :ta_mappings
-
-
1
QUESTIONNAIRE = [['My questionnaires','list_mine'],
-
['All public questionnaires','list_all']]
-
-
1
ASSIGNMENT = [['My assignments','list_mine'],
-
['All public assignments','list_all']]
-
-
1
def list_all(object_type, user_id)
-
object_type.find(:all,
-
:conditions => ["instructor_id = ? OR private = 0", user_id])
-
end
-
-
1
def list_mine(object_type, user_id)
-
-
#### if we are loading "My Assignments" for a user who is a TA we need to find all assignments
-
#### which are assigned to a course for which the user is a TA (in addition to his own assignments
-
#### which he created
-
if(object_type.to_s.eql? "Assignment")
-
#### once the course_id on the assignments table is being assigned properly we can use
-
#### this find method, until then use the one below.
-
#Assignment.find_by_sql(["select assignments.id, assignments.name, assignments.directory_path " +
-
# "from assignments inner join ta_mappings ON (assignments.course_id=ta_mappings.course_id and ta_id=?) " +
-
# "UNION select assignments.id, assignments.name, assignments.directory_path from assignments where instructor_id=?",user_id,user_id])
-
-
#### this find method compares the directories of an assignment and a course to find out if the
-
#### the assignment is in a subdirectory of a course that the user is a TA for.
-
Assignment.find_by_sql(["select assignments.id, assignments.name, assignments.directory_path " +
-
"from assignments, ta_mappings where assignments.course_id = ta_mappings.course_id and ta_mappings.ta_id=?",user_id])
-
else
-
object_type.find(:all, :conditions => ["instructor_id = ?", user_id])
-
end
-
end
-
-
1
def get(object_type, id, user_id)
-
object_type.find(:first,
-
:conditions => ["id = ? AND (instructor_id = ? OR private = 0)",
-
id, user_id])
-
end
-
-
1
def self.get_my_instructor(user_id)
-
course_id = TaMapping.get_course_id(user_id)
-
Course.find(course_id).instructor_id
-
end
-
-
1
def self.get_mapped_instructor_ids(user_id)
-
ids = Array.new
-
mappings = TaMapping.find_all_by_ta_id(user_id)
-
mappings.each{
-
|map|
-
ids << map.course.instructor.id
-
}
-
return ids
-
end
-
-
1
def self.get_mapped_courses(user_id)
-
ids = Array.new
-
mappings = TaMapping.find_all_by_ta_id(user_id)
-
mappings.each{
-
|map|
-
ids << map.course.id
-
}
-
return ids
-
end
-
-
1
def get_instructor
-
Ta.get_my_instructor(self.id)
-
end
-
-
1
def set_instructor (new_assign)
-
new_assign.instructor_id = Ta.get_my_instructor(self.id)
-
new_assign.course_id = TaMapping.get_course_id(self.id)
-
end
-
-
1
def set_courses_to_assignment
-
@courses = TaMapping.get_courses(self.id)
-
end
-
-
1
def is_teaching_assistant?
-
return true
-
end
-
-
end
-
1
class TaMapping < ActiveRecord::Base
-
1
belongs_to :course
-
1
belongs_to :ta
-
1
def self.get_course_id(user_id)
-
TaMapping.find_by_ta_id(user_id).course_id
-
end
-
1
def self.get_courses(user_id)
-
Course.find(:all, :conditions=> ["id=?",TaMapping.find_by_ta_id(user_id).course_id])
-
end
-
end
-
1
class Team < ActiveRecord::Base
-
1
has_many :teams_users
-
1
has_many :users, :through => :teams_users
-
1
has_many :join_team_requests
-
-
1
def get_participants
-
Participant.find_all_by_id users.map(&:id)
-
end
-
-
1
def delete
-
for teamsuser in TeamsUser.find(:all, :conditions => ["team_id =?", self.id])
-
teamsuser.delete
-
end
-
node = TeamNode.find_by_node_object_id(self.id)
-
if node
-
node.destroy
-
end
-
self.destroy
-
end
-
-
1
def get_participants
-
Participant.where user_id: users.map(&:id), parent_id: parent_id
-
end
-
-
1
def get_node_type
-
"TeamNode"
-
end
-
-
1
def get_author_name
-
return self.name
-
end
-
-
1
def self.generate_team_name()
-
counter = 0
-
while (true)
-
temp = "Team #{counter}"
-
if (!Team.find_by_name(temp))
-
return temp
-
end
-
counter=counter+1
-
end
-
end
-
-
1
def get_possible_team_members(name)
-
query = "select users.* from users, participants"
-
query = query + " where users.id = participants.user_id"
-
query = query + " and participants.type = '"+self.get_participant_type+"'"
-
query = query + " and participants.parent_id = #{self.parent_id}"
-
query = query + " and users.name like '#{name}%'"
-
query = query + " order by users.name"
-
User.find_by_sql(query)
-
end
-
-
1
def has_user(user)
-
users.include? user
-
end
-
-
1
def add_member(user, assignment_id)
-
if has_user(user)
-
raise "\""+user.name+"\" is already a member of the team, \""+self.name+"\""
-
end
-
-
if assignment_id==nil
-
can_add_member=true
-
else
-
max_team_members=Assignment.find(assignment_id).max_team_size
-
curr_team_size= TeamsUser.count(:conditions => ["team_id = ?", self.id])
-
can_add_member = (curr_team_size < max_team_members)
-
end
-
-
if can_add_member
-
t_user = TeamsUser.create(:user_id => user.id, :team_id => self.id)
-
parent = TeamNode.find_by_node_object_id(self.id)
-
TeamUserNode.create(:parent_id => parent.id, :node_object_id => t_user.id)
-
add_participant(self.parent_id, user)
-
end
-
-
return can_add_member
-
end
-
-
1
def copy_members(new_team)
-
members = TeamsUser.find_all_by_team_id(self.id)
-
members.each{
-
| member |
-
t_user = TeamsUser.create(:team_id => new_team.id, :user_id => member.user_id)
-
parent = Object.const_get(self.get_parent_model).find(self.parent_id)
-
TeamUserNode.create(:parent_id => parent.id, :node_object_id => t_user.id)
-
}
-
end
-
-
#TODO: no way in hell this method works
-
1
def self.create_node_object(name, parent_id)
-
create(:name => name, :parent_id => parent_id)
-
parent = Object.const_get(self.get_parent_model).find(parent_id)
-
Object.const_get(self.get_node_type).create(:parent_id => parent.id, :node_object_id => self.id)
-
end
-
-
1
def self.check_for_existing(parent, name, team_type)
-
list = Object.const_get(team_type + 'Team').find(:all, :conditions => ['parent_id = ? and name = ?', parent.id, name])
-
if list.length > 0
-
raise TeamExistsError, 'Team name, "' + name + '", is already in use.'
-
end
-
end
-
-
1
def self.delete_all_by_parent(parent)
-
teams = Team.find(:all, :conditions => ["parent_id=?", parent.id])
-
-
for team in teams
-
team.delete
-
end
-
end
-
-
# @param parent [Object]
-
# @param team_type [Object]
-
# @param team_size [Object]
-
1
def self.randomize_all_by_parent(parent, team_type, team_size)
-
participants = Participant.find(:all, :conditions => ["parent_id = ? AND type = ?", parent.id, parent.class.to_s + "Participant"])
-
participants = participants.sort{rand(3) - 1}
-
users = participants.map{|p| User.find_by_id(p.user_id)}
-
#users = users.uniq
-
-
Team.delete_all_by_parent(parent)
-
-
no_of_teams = users.length.fdiv(team_size).ceil
-
nextTeamMemberIndex = 0
-
-
for i in 1..no_of_teams
-
team = Object.const_get(team_type + 'Team').create(:name => "Team #{i}", :parent_id => parent.id)
-
TeamNode.create(:parent_id => parent.id, :node_object_id => team.id)
-
-
team_size.times do
-
break if nextTeamMemberIndex >= users.length
-
-
user = users[nextTeamMemberIndex]
-
team.add_member(user)
-
-
nextTeamMemberIndex += 1
-
end
-
end
-
end
-
-
1
def self.generate_team_name(teamnameprefix)
-
counter = 1
-
while (true)
-
teamname = teamnameprefix + "_Team#{counter}"
-
if (!Team.find_by_name(teamname))
-
return teamname
-
end
-
counter=counter+1
-
end
-
end
-
-
1
def import_team_members(starting_index, row)
-
puts ">>>in import_team_members, row.length = " + row.length.to_s
-
index = starting_index
-
while(index < row.length)
-
puts ">>> user_id:" + row[index].to_s.strip
-
user = User.find_by_name(row[index].to_s.strip)
-
if user.nil?
-
raise ImportError, "The user \""+row[index].to_s.strip+"\" was not found. <a href='/users/new'>Create</a> this user?"
-
else
-
if TeamsUser.find(:first, :conditions => ["team_id =? and user_id =?", id, user.id]).nil?
-
add_member(user, nil)
-
end
-
end
-
index = index + 1
-
end
-
end
-
end
-
1
class TeamExistsError < StandardError
-
end
-
1
class TeamNode < Node
-
1
belongs_to :node_object, class_name: 'Team'
-
-
1
def self.table
-
"teams"
-
end
-
-
1
def self.get(parent_id)
-
query = "select nodes.* from nodes, "+self.table
-
query = query+" where nodes.node_object_id = "+self.table+".id"
-
query = query+" and nodes.type = '"+self.to_s+"'"
-
if parent_id
-
query = query+ " and "+self.table+".parent_id = "+parent_id.to_s
-
end
-
find_by_sql(query)
-
end
-
-
1
def get_name
-
Team.find(self.node_object_id).name
-
end
-
-
1
def get_children(sortvar = nil,sortorder = nil,user_id = nil,parent_id = nil)
-
TeamUserNode.get(self.node_object_id)
-
end
-
end
-
1
class TeamReviewResponseMap < ReviewResponseMap
-
1
belongs_to :reviewee, :class_name => 'Team', :foreign_key => 'reviewee_id'
-
1
belongs_to :contributor, :class_name => 'Team', :foreign_key => 'reviewee_id'
-
-
end
-
1
class TeamUserNode < Node
-
1
belongs_to :node_object, class_name: 'TeamsUser'
-
-
1
def self.table
-
"teams_users"
-
end
-
-
1
def get_name
-
TeamsUser.find(self.node_object_id).name
-
end
-
-
1
def self.get(parent_id)
-
query = "select nodes.* from nodes, "+self.table
-
query = query+" where nodes.node_object_id = "+self.table+".id"
-
query = query+" and nodes.type = '"+self.to_s+"'"
-
if parent_id
-
query = query+ " and "+self.table+".team_id = "+parent_id.to_s
-
end
-
find_by_sql(query)
-
end
-
-
1
def is_leaf
-
true
-
end
-
end
-
1
class TeammateReviewQuestionnaire < Questionnaire
-
1
def after_initialize
-
self.display_type = 'Teammate Review'
-
end
-
-
1
def symbol
-
return "teammate".to_sym
-
end
-
-
1
def get_assessments_for(participant)
-
participant.get_teammate_reviews()
-
end
-
-
-
end
-
1
class TeammateReviewResponseMap < ResponseMap
-
1
belongs_to :reviewee, :class_name => 'Participant', :foreign_key => 'reviewee_id'
-
1
belongs_to :assignment, :class_name => 'Assignment', :foreign_key => 'reviewed_object_id'
-
-
1
def questionnaire
-
self.assignment.questionnaires.find_by_type('TeammateReviewQuestionnaire')
-
end
-
-
1
def contributor
-
nil
-
end
-
-
1
def get_title
-
return "Teammate Review"
-
end
-
end
-
1
class TeamsParticipant < ActiveRecord::Base
-
1
belongs_to :user
-
1
belongs_to :team
-
-
1
def name
-
self.user.name
-
end
-
-
1
def delete
-
TeamUserNode.find_by_node_object_id(self.id)
-
team = self.team
-
self.destroy
-
if team.teams_participants.length == 0
-
team.delete
-
end
-
end
-
-
1
def hello
-
return "Hello"
-
end
-
-
1
def get_team_members(team_id)
-
-
-
-
end
-
end
-
1
class TeamsUser < ActiveRecord::Base
-
1
belongs_to :user
-
1
belongs_to :team
-
-
1
def name
-
self.user.name
-
end
-
-
1
def delete
-
TeamUserNode.find_by_node_object_id(self.id)
-
team = self.team
-
self.destroy
-
if team.teams_users.length == 0
-
team.delete
-
end
-
end
-
-
1
def hello
-
return "Hello"
-
end
-
-
1
def get_team_members(team_id)
-
-
-
-
end
-
end
-
1
class TopicDeadline < ActiveRecord::Base
-
1
belongs_to :topic, :class_name => 'SignUpTopic'
-
-
1
validate :due_at_is_valid_datetime
-
-
1
def due_at_is_valid_datetime
-
errors.add(:due_at, 'must be a valid datetime') if ((DateTime.strptime(due_at.to_s, '%Y-%m-%d %H:%M:%S') rescue ArgumentError) == ArgumentError)
-
end
-
end
-
1
class TopicDependency < ActiveRecord::Base
-
1
serialize :dependent_on
-
-
1
def self.save_dependency(topics)
-
topics.each {|topic|
-
#topic[0] => topic_id and topic[1] => dependent_on
-
topic_dependency = TopicDependency.find_by_topic_id(topic[0])
-
if topic_dependency == nil
-
topic_dependency = TopicDependency.new
-
topic_dependency.topic_id = topic[0]
-
end
-
dependency_list = topic[1].collect{|i| i.to_i}
-
topic_dependency.dependent_on = dependency_list
-
topic_dependency.save
-
}
-
end
-
-
end
-
1
class TreeFolder < ActiveRecord::Base
-
end
-
1
class User < ActiveRecord::Base
-
-
1
acts_as_authentic do |config|
-
13
config.validates_uniqueness_of_email_field_options = {:if => lambda { false }} # Don't validate email uniqueness
-
1
config.crypto_provider = Authlogic::CryptoProviders::Sha1
-
1
Authlogic::CryptoProviders::Sha1.join_token = ''
-
1
Authlogic::CryptoProviders::Sha1.stretches = 1
-
end
-
-
1
has_many :participants, :class_name => 'Participant', :foreign_key => 'user_id', :dependent => :destroy
-
1
has_many :assignment_participants, :class_name => 'AssignmentParticipant', :foreign_key => 'user_id', :dependent => :destroy
-
1
has_many :assignments, :through => :participants
-
-
1
has_many :teams_users, :dependent => :destroy
-
1
has_many :teams, :through => :teams_users
-
-
1
has_many :children, class_name: 'User', :foreign_key => 'parent_id'
-
1
belongs_to :parent, class_name: 'User'
-
1
belongs_to :role
-
-
1
validates_presence_of :name
-
1
validates_uniqueness_of :name
-
-
1
validates_presence_of :email, :message => "can't be blank"
-
1
validates_format_of :email, :with => /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i, :allow_blank => true
-
-
13
before_validation :randomize_password, :if => lambda { |user| user.new_record? && user.password.blank? } # AuthLogic
-
1
after_create :email_welcome
-
-
1
scope :superadministrators, -> { where role_id: Role.superadministrator }
-
1
scope :superadmins, -> { superadministrators }
-
1
scope :administrators, -> { where role_id: Role.administrator }
-
1
scope :admins, -> { administrators }
-
2
scope :instructors, -> { where role_id: Role.instructor }
-
1
scope :tas, -> { where role_id: Role.ta }
-
1
scope :students, -> { where role_id: Role.student }
-
-
1
def salt_first?
-
22
true
-
end
-
-
1
def get_available_users(name)
-
lesser_roles = role.get_parents
-
all_users = User.find(:all, :conditions => ['name LIKE ?', "#{name}%"], :limit => 20) # higher limit, since we're filtering
-
visible_users = all_users.select{|user| lesser_roles.include? user.role}
-
return visible_users[0,10] # the first 10
-
end
-
-
1
def can_impersonate?(user)
-
user &&
-
self == user || # can impersonate self
-
self.is_teaching_assistant_for?(user) || #TAs can impersonate their students
-
self.is_creator_of?(user) ||
-
can_impersonate?(user.parent) # recursive
-
end
-
-
1
def first_name
-
8
fullname[/,.+/][/\w+/] if fullname
-
end
-
-
1
def super_admin?
-
role.name == 'Super-Administrator'
-
end
-
-
1
def admin?
-
role.name == 'Administrator' || super_admin?
-
end
-
-
1
def is_creator_of?(user)
-
self == user.creator
-
end
-
-
1
def assign_random_password
-
if self.password.blank?
-
self.password = self.random_password
-
end
-
end
-
-
# Function which has a MailerHelper which sends the mail welcome email to the user after signing up
-
1
def email_welcome
-
8
MailerHelper::send_mail_to_user(self, "Your Expertiza password has been created", "user_welcome", password)
-
end
-
-
1
def check_password(password)
-
Authlogic::CryptoProviders::Sha1.stretches = 1
-
Authlogic::CryptoProviders::Sha1.matches?(password, *[self.password_salt.to_s + password])
-
end
-
-
# Resets the password to be mailed to the user
-
1
def reset_password
-
randomize_password
-
save
-
password
-
end
-
-
1
def self.random_password(size=8)
-
random_pronouncable_password((size/2).round) + rand.to_s[2,3]
-
end
-
-
1
def self.import(row,session,id = nil)
-
if row.length != 4
-
raise ArgumentError, "Not enough items"
-
end
-
user = User.find_by_name(row[0])
-
-
if user == nil
-
attributes = ImportFileHelper::define_attributes(row)
-
user = ImportFileHelper::create_new_user(attributes,session)
-
else
-
user.password = row[3].strip
-
user.email = row[2].strip
-
user.fullname = row[1].strip
-
user.parent_id = (session[:user]).id
-
user.save
-
end
-
end
-
-
1
def get_author_name
-
return self.fullname
-
end
-
-
1
def self.yesorno(elt)
-
if elt==true
-
"yes"
-
elsif elt ==false
-
"no"
-
else
-
""
-
end
-
end
-
-
# locate User based on provided login.
-
# If user supplies e-mail or name, the
-
# helper will try to find that User account.
-
1
def self.find_by_login(login)
-
11
user = User.find_by_email(login)
-
11
if user == nil
-
11
items = login.split("@")
-
11
shortName = items[0]
-
11
userList = User.find(:all, {:conditions=> ["name =?",shortName]})
-
11
if userList != nil && userList.length == 1
-
11
user = userList.first
-
end
-
end
-
11
return user
-
end
-
-
1
def set_instructor (new_assign)
-
new_assign.instructor_id = self.id
-
end
-
-
1
def get_instructor
-
self.id
-
end
-
-
1
def instructor_id
-
case role.name
-
when 'Instructor' then id
-
when 'Teaching Assistant' then Ta.get_my_instructor(id)
-
else raise NotImplementedError.new "for role #{role.name}"
-
end
-
end
-
-
1
def set_courses_to_assignment
-
@courses = Course.find_all_by_instructor_id(self.id, :order => 'name')
-
end
-
-
# generate a new RSA public/private key pair and create our own X509 digital certificate which we
-
# save in the database. The private key is returned by the method but not saved.
-
1
def generate_keys
-
# check if we are replacing a digital certificate already generated
-
replacing_key = true if (!self.digital_certificate.nil?)
-
-
# generate the new key pair
-
new_key = OpenSSL::PKey::RSA.generate( 1024 )
-
self.public_key = new_key.public_key.to_pem
-
-
save
-
-
# when replacing an existing key, update any digital signatures made previously with the new key
-
if (replacing_key)
-
participants = AssignmentParticipant.find_all_by_user_id(self.id)
-
for participant in participants
-
if (participant.permission_granted)
-
AssignmentParticipant.grant_publishing_rights(new_key.to_pem, [ participant ])
-
end
-
end
-
end
-
-
# return the new private key
-
new_key.to_pem
-
end
-
-
1
def initialize(attributes = nil)
-
9
super(attributes)
-
9
Authlogic::CryptoProviders::Sha1.stretches = 1
-
9
@email_on_review = true
-
9
@email_on_submission = true
-
9
@email_on_review_of_review = true
-
end
-
-
1
def self.export(csv, parent_id, options)
-
users = User.find(:all)
-
users.each {|user|
-
tcsv = Array.new
-
if (options["personal_details"] == "true")
-
tcsv.push(user.name, user.fullname, user.email)
-
end
-
if (options["role"] == "true")
-
tcsv.push(user.role.name)
-
end
-
if (options["parent"] == "true")
-
tcsv.push(user.parent.name)
-
end
-
if (options["email_options"] == "true")
-
tcsv.push(user.email_on_submission, user.email_on_review, user.email_on_review_of_review)
-
end
-
if (options["handle"] == "true")
-
tcsv.push(user.handle)
-
end
-
csv << tcsv
-
}
-
end
-
-
1
def creator
-
parent
-
end
-
-
1
def self.get_export_fields(options)
-
fields = Array.new
-
if (options["personal_details"] == "true")
-
fields.push("name", "full name", "email")
-
end
-
if (options["role"] == "true")
-
fields.push("role")
-
end
-
if (options["parent"] == "true")
-
fields.push("parent")
-
end
-
if (options["email_options"] == "true")
-
fields.push("email on submission", "email on review", "email on metareview")
-
end
-
if (options["handle"] == "true")
-
fields.push("handle")
-
end
-
return fields
-
end
-
-
1
def self.from_params(params)
-
if params[:user_id]
-
user = User.find(params[:user_id])
-
else
-
user = User.find_by_name(params[:user][:name])
-
end
-
if user.nil?
-
newuser = url_for :controller => 'users', :action => 'new'
-
raise "Please <a href='#{newuser}'>create an account</a> for this user to continue."
-
end
-
return user
-
end
-
-
1
def is_teaching_assistant_for?(student)
-
return false if self.role.name != 'Teaching Assistant'
-
return false if student.role.name != 'Student'
-
return true if Course.all.any? do |c|
-
c.participants.all(:conditions => "user_id=#{student.id}").size > 0 &&
-
c.participants.all(:conditions => "user_id=#{id}").size > 0
-
end
-
return false
-
end
-
-
1
def is_teaching_assistant?
-
130
false
-
end
-
-
end
-
1
class Waitlist < ActiveRecord::Base
-
end
-
1
class WikiType < ActiveRecord::Base
-
1
has_many :assignments
-
1
require 'open-uri'
-
1
require 'time'
-
-
##
-
# review_mediawiki
-
#
-
# author: Jeffrey T. Haug
-
#
-
# usage: To be used in a view such as:
-
#
-
# <%= review_mediawiki 'http://pg-server.ece.ncsu.edu/mediawiki/index.php/ECE633:hw1', '2007/06/11', 'jthaug' %>
-
#
-
# @args: _assignment_url (URL of the wiki assignment.)
-
# @args: _start_date (all review items older will be filtered out)
-
# @args: _wiki_user (wiki user id to crawl)
-
##
-
1
def self.review_mediawiki(_assignment_url, _start_date = nil, _wiki_user = nil)
-
response = '' #the response from the URL
-
-
#Check to make sure we were passed a valid URL
-
matches = /http:/.match( _assignment_url )
-
if not matches
-
return response
-
end
-
-
#Args
-
url = _assignment_url.chomp("/")
-
wiki_url = _assignment_url.scan(/(.*?)index.php/)
-
namespace = _assignment_url.split(/\//)
-
namespace_url = namespace.last
-
-
#Media Wiki Specific
-
review = "index.php?title=Special:Contributions&target=" + _wiki_user
-
-
-
#Grab this user's contributions
-
url = wiki_url[0].to_s + review
-
open(url,
-
"User-Agent" => "Ruby/#{RUBY_VERSION}",
-
"From" => "email@addr.com", #Put pg admin email address here
-
"Referer" => "http://") { |f| #Put pg URL here
-
# Save the response body
-
response = f.read
-
}
-
-
#Clean URLs
-
response = response.gsub(/href=\"(.*?)index.php/,'href="' + wiki_url[0].to_s + 'index.php')
-
-
#Mediawiki uses a structure like:
-
# <!-- start content -->
-
# Content
-
# <!-- end content -->
-
#
-
#Get everything between the words "wikipage"
-
changes = response.split(/<!-- start content -->/)
-
changes2 = changes[1].split(/<!-- end content -->/)
-
response = changes2[0]
-
-
#Extract each line item
-
line_items = response.scan(/<li>.*<\/li>/)
-
-
#Extract the dates only
-
dates = response.scan(/\d\d:\d\d, \d+ \w+ \d\d\d\d/)
-
-
#if start date provided we only want date line items since start date
-
if _start_date
-
-
-
#NOTE: The date_lines index = dates index
-
-
#Convert _start_date
-
start_date = Time.parse(_start_date)
-
-
#Remove dates before deadline
-
dates.each_with_index do |date, index|
-
-
#The date is before start of review
-
if Time.parse(date) < start_date
-
line_items.delete_at(index)
-
end
-
-
end
-
-
end
-
-
-
#Remove line items that not in this namespace
-
line_items.each_with_index do |item, index|
-
-
scan_result = item.scan(namespace_url)
-
-
if not namespace_url === scan_result[0]
-
line_items[index] = nil
-
end
-
-
end
-
-
line_items.compact!
-
-
formatted_line_items =Array.new
-
formatted_line_items << "<ul>"
-
formatted_line_items << line_items
-
formatted_line_items << "</ul>"
-
return formatted_line_items
-
end
-
-
##
-
# review_dokuwiki
-
#
-
# author: Jeffrey T. Haug
-
#
-
# usage: To be used in a view such as:
-
#
-
# <%= review_dokuwiki 'http://pg-server.ece.ncsu.edu/dokuwiki/doku.php/ece633:hw1', '2007/06/11', 'jthaug' %>
-
#
-
# @args: _assignment_url (URL of the wiki assignment.)
-
# @args: _start_date (all review items older will be filtered out)
-
# @args: _wiki_user (wiki user id to crawl)
-
##
-
1
def review_dokuwiki(_assignment_url, _start_date = nil, _wiki_user = nil)
-
-
response = '' #the response from the URL
-
-
#Check to make sure we were passed a valid URL
-
matches = /http:/.match( _assignment_url )
-
if not matches
-
return response
-
end
-
-
#Args
-
url = _assignment_url.chomp("/")
-
wiki_url = _assignment_url.scan(/(.*?)doku.php/)
-
namespace = _assignment_url.split(/\//)
-
namespace_url = namespace.last
-
-
#Doku Wiki Specific
-
index = "?idx=" + namespace_url
-
review = "?do=revisions" #"?do=recent"
-
-
-
#Grab all relevant urls from index page ####################
-
url += index
-
open(url,
-
"User-Agent" => "Ruby/#{RUBY_VERSION}",
-
"From" => "email@addr.com", #Put pg admin email address here
-
"Referer" => "http://") { |f| #Put pg URL here
-
-
# Save the response body
-
response = f.read
-
-
}
-
-
#Clean URLs
-
response = response.gsub(/href=\"(.*?)doku.php/, 'href="' + wiki_url[0].to_s + 'doku.php')
-
-
#Get all URLs
-
index_urls = response.scan(/href=\"(.*?)\"/)
-
-
namespace_urls = Array.new #Create array to store all URLs in this namespace
-
namespace_urls << _assignment_url
-
-
#Narrow down to all URLs in our namespace
-
index_urls.each_with_index do |index_url, index|
-
-
scan_result = index_url[0].scan(_assignment_url + ":") #scan current item
-
-
if _assignment_url + ":" === scan_result[0]
-
namespace_urls << index_urls[index].to_s
-
end
-
-
end
-
-
#Create a array for all of our review_items
-
review_items = Array.new
-
-
#Process Each page in our namespace
-
namespace_urls.each_with_index do |cur_url, index|
-
-
#return cur_url + review
-
url = namespace_urls[index].to_s
-
url += review
-
#return url
-
open(url,
-
"User-Agent" => "Ruby/#{RUBY_VERSION}",
-
"From" => "email@addr.com", #Put pg admin email address here
-
"Referer" => "http://") { |f| #Put pg URL here
-
-
# Save the response body
-
response = f.read
-
-
}
-
-
## DOKUWIKI PARSING
-
-
#Clean URLs
-
response = response.gsub(/href=\"(.*?)doku.php/,'href="' + wiki_url[0].to_s + 'doku.php')
-
-
# Luckily, dokuwiki uses a structure like:
-
# <!-- wikipage start -->
-
# Content
-
# <!-- wikipage stop -->
-
#
-
#Get everything between the words "wikipage"
-
changes = response.split(/wikipage/)
-
#Trim the "start -->" from "<!-- wikipage start -->"
-
changes = changes[1].sub(/start -->/,"")
-
#Trim the "<!--" from "<!-- wikipage stop -->"
-
response = changes.sub(/<!--/,"")
-
-
-
#Extract each line item
-
line_items = response.scan(/<li>(.*?)<\/li>/)
-
-
#Extract the dates only
-
dates = response.scan(/\d\d\d\d\/\d\d\/\d\d \d\d\:\d\d/)
-
-
-
#if wiki username provided we only want their line items
-
if _wiki_user
-
-
#Remove line items that do not contain this user
-
line_items.each_with_index do |item, index|
-
-
scan_result = item[0].scan(_wiki_user) #scan current item
-
-
if not _wiki_user === scan_result[0] #no match for wiki user --> eliminate
-
line_items[index] = nil
-
dates[index] = nil
-
end
-
-
end
-
-
line_items.compact!
-
dates.compact!
-
end
-
-
#if start date provided we only want date line items since start date
-
if _start_date
-
-
-
#NOTE: The date_lines index = dates index
-
-
#Convert _start_date
-
start_date = Time.parse(_start_date)
-
-
#Remove dates before deadline
-
dates.each_with_index do |date, index|
-
-
#The date is before start of review
-
if Time.parse(date) < start_date
-
line_items.delete_at(index)
-
end
-
-
end
-
-
end
-
-
-
review_items = review_items + line_items
-
-
end
-
-
return review_items
-
end
-
-
1
def self.review_mediawiki_group(_assignment_url, _start_date = nil, _wiki_user = nil)
-
line_items = review_mediawiki(_assignment_url, _start_date , _wiki_user)
-
return line_items.first(3)
-
end
-
end
-
# GoldbergFilters
-
-
-
1
module GoldbergFilters
-
-
1
def goldberg_security_filter
-
@settings = SystemSettings.find(:first)
-
-
if @settings
-
make_public = false # Going to check if we need to
-
-
# If there's already a session, check that it's still up to date
-
if session[:credentials] and session[:credentials].role_id
-
role = Role.find(session[:credentials].role_id)
-
if role
-
# Check if the role has been updated
-
if role.updated_at > session[:credentials].updated_at
-
menu_selection = session[:menu].selected # remember this
-
session[:credentials] = role.cache[:credentials]
-
session[:menu] = role.cache[:menu]
-
if menu_selection
-
session[:menu].select(menu_selection)
-
end
-
else
-
# Role is still current: no action required here
-
logger.info "(Role still current)"
-
end
-
else # No such Role: must have been deleted?
-
make_public = true
-
end
-
else # No credentials
-
make_public = true
-
end
-
-
if make_public
-
public_role = Role.find(@settings.public_role_id)
-
if !public_role.cache.is_a?(Hash) || !public_role ||
-
!public_role.cache ||
-
!public_role.cache.try(:[], :credentials) ||
-
!public_role.cache.try(:[], :menu)
-
Role.rebuild_cache
-
public_role = Role.find(@settings.public_role_id)
-
end
-
-
session[:credentials] = public_role.cache[:credentials]
-
session[:menu] = public_role.cache[:menu]
-
end
-
-
if session[:credentials].role_id != @settings.public_role_id
-
logger.info "(Logged-in user)"
-
if session[:last_time] != nil
-
if (Time.now - session[:last_time]) > @settings.session_timeout
-
logger.info "Session: time expired"
-
AuthController.logout(session)
-
redirect_to @settings.session_expired_page.url
-
return false
-
else
-
logger.info "Session: time NOT expired"
-
end
-
end
-
end
-
-
# If this is a page request check that it exists, and if not
-
# redirect to the "unknown" page
-
if params[:controller] == 'content_pages' and
-
params[:action] == 'view'
-
if not session[:credentials].pages.has_key?(params[:page_name].to_s)
-
logger.warn "(Unknown page? #{params[:page_name].to_s})"
-
redirect_to @settings.not_found_page.url
-
return false
-
end
-
end
-
-
# PERMISSIONS
-
# Check whether the user is authorised for this page or action.
-
if !AuthController.authorised?(session, params)
-
redirect_to @settings.permission_denied_page.url
-
return false
-
end
-
end # if @settings
-
-
session[:last_time] = Time.now
-
-
return true
-
end
-
end
-
1
module ActiveRecord
-
1
module Acts #:nodoc:
-
1
module NestedSet #:nodoc:
-
1
def self.included(base)
-
1
base.extend(ClassMethods)
-
end
-
-
# This +acts_as+ extension provides Nested Set functionality. Nested Set is similiar to Tree, but with
-
# the added feature that you can select the children and all of their descendents with
-
# a single query. A good use case for this is a threaded post system, where you want
-
# to display every reply to a comment without multiple selects.
-
#
-
# A Google search for "Nested Set" should point you to in the right direction to explain the
-
# database theory. I figured out a bunch of this from
-
# http://threebit.net/tutorials/nestedset/tutorial1.html
-
#
-
# Instead of picturing a leaf node structure with children pointing back to their parent,
-
# the best way to imagine how this works is to think of the parent entity surrounding all
-
# of its children, and its parent surrounding it, etc. Assuming that they are lined up
-
# horizontally, we store the left and right boundries in the database.
-
#
-
# Imagine:
-
# root
-
# |_ Child 1
-
# |_ Child 1.1
-
# |_ Child 1.2
-
# |_ Child 2
-
# |_ Child 2.1
-
# |_ Child 2.2
-
#
-
# If my cirlces in circles description didn't make sense, check out this sweet
-
# ASCII art:
-
#
-
# ___________________________________________________________________
-
# | Root |
-
# | ____________________________ ____________________________ |
-
# | | Child 1 | | Child 2 | |
-
# | | __________ _________ | | __________ _________ | |
-
# | | | C 1.1 | | C 1.2 | | | | C 2.1 | | C 2.2 | | |
-
# 1 2 3_________4 5________6 7 8 9_________10 11_______12 13 14
-
# | |___________________________| |___________________________| |
-
# |___________________________________________________________________|
-
#
-
# The numbers represent the left and right boundries. The table then might
-
# look like this:
-
# ID | PARENT | LEFT | RIGHT | DATA
-
# 1 | 0 | 1 | 14 | root
-
# 2 | 1 | 2 | 7 | Child 1
-
# 3 | 2 | 3 | 4 | Child 1.1
-
# 4 | 2 | 5 | 6 | Child 1.2
-
# 5 | 1 | 8 | 13 | Child 2
-
# 6 | 5 | 9 | 10 | Child 2.1
-
# 7 | 5 | 11 | 12 | Child 2.2
-
#
-
# So, to get all children of an entry, you
-
# SELECT * WHERE CHILD.LEFT IS BETWEEN PARENT.LEFT AND PARENT.RIGHT
-
#
-
# To get the count, it's <tt>(LEFT - RIGHT + 1)/2</tt>, etc.
-
#
-
# To get the direct parent, it falls back to using the +PARENT_ID+ field.
-
#
-
# There are instance methods for all of these.
-
#
-
# The structure is good if you need to group things together; the downside is that
-
# keeping data integrity is a pain, and both adding and removing an entry
-
# require a full table write.
-
#
-
# This sets up a +before_destroy+ callback to prune the tree correctly if one of its
-
# elements gets deleted.
-
#
-
1
module ClassMethods
-
# Configuration options are:
-
#
-
# * +parent_column+ - specifies the column name to use for keeping the position integer (default: +parent_id+)
-
# * +left_column+ - column name for left boundry data, default +lft+
-
# * +right_column+ - column name for right boundry data, default +rgt+
-
# * +scope+ - restricts what is to be considered a list. Given a symbol, it'll attach <tt>_id</tt>
-
# (if it hasn't already been added) and use that as the foreign key restriction. It's also possible
-
# to give it an entire string that is interpolated if you need a tighter scope than just a foreign key.
-
# Example: <tt>acts_as_nested_set :scope => 'todo_list_id = #{todo_list_id} AND completed = 0'</tt>
-
1
def acts_as_nested_set(options = {})
-
1
configuration = { :parent_column => "parent_id", :left_column => "lft", :right_column => "rgt", :scope => "1 = 1" }
-
-
1
configuration.update(options) if options.is_a?(Hash)
-
-
1
configuration[:scope] = "#{configuration[:scope]}_id".intern if configuration[:scope].is_a?(Symbol) && configuration[:scope].to_s !~ /_id$/
-
-
1
if configuration[:scope].is_a?(Symbol)
-
scope_condition_method = %(
-
def scope_condition
-
if #{configuration[:scope].to_s}.nil?
-
"#{configuration[:scope].to_s} IS NULL"
-
else
-
"#{configuration[:scope].to_s} = \#{#{configuration[:scope].to_s}}"
-
end
-
end
-
)
-
else
-
1
scope_condition_method = "def scope_condition() \"#{configuration[:scope]}\" end"
-
end
-
-
class_eval <<-EOV
-
include ActiveRecord::Acts::NestedSet::InstanceMethods
-
-
#{scope_condition_method}
-
-
def left_col_name() "#{configuration[:left_column]}" end
-
-
def right_col_name() "#{configuration[:right_column]}" end
-
-
def parent_column() "#{configuration[:parent_column]}" end
-
-
1
EOV
-
end
-
end
-
-
1
module InstanceMethods
-
# Returns +true+ is this is a root node.
-
1
def root?
-
parent_id = self[parent_column]
-
(parent_id == 0 || parent_id.nil?) && (self[left_col_name] == 1) && (self[right_col_name] > self[left_col_name])
-
end
-
-
# Returns +true+ is this is a child node
-
1
def child?
-
parent_id = self[parent_column]
-
!(parent_id == 0 || parent_id.nil?) && (self[left_col_name] > 1) && (self[right_col_name] > self[left_col_name])
-
end
-
-
# Returns +true+ if we have no idea what this is
-
1
def unknown?
-
!root? && !child?
-
end
-
-
# Adds a child to this object in the tree. If this object hasn't been initialized,
-
# it gets set up as a root node. Otherwise, this method will update all of the
-
# other elements in the tree and shift them to the right, keeping everything
-
# balanced.
-
1
def add_child( child )
-
self.reload
-
child.reload
-
-
if child.root?
-
raise "Adding sub-tree isn\'t currently supported"
-
else
-
if ( (self[left_col_name] == nil) || (self[right_col_name] == nil) )
-
# Looks like we're now the root node! Woo
-
self[left_col_name] = 1
-
self[right_col_name] = 4
-
-
# What do to do about validation?
-
return nil unless self.save
-
-
child[parent_column] = self.id
-
child[left_col_name] = 2
-
child[right_col_name]= 3
-
return child.save
-
else
-
# OK, we need to add and shift everything else to the right
-
child[parent_column] = self.id
-
right_bound = self[right_col_name]
-
child[left_col_name] = right_bound
-
child[right_col_name] = right_bound + 1
-
self[right_col_name] += 2
-
self.class.base_class.transaction {
-
self.class.base_class.update_all( "#{left_col_name} = (#{left_col_name} + 2)", "#{scope_condition} AND #{left_col_name} >= #{right_bound}" )
-
self.class.base_class.update_all( "#{right_col_name} = (#{right_col_name} + 2)", "#{scope_condition} AND #{right_col_name} >= #{right_bound}" )
-
self.save
-
child.save
-
}
-
end
-
end
-
end
-
-
# Returns the number of nested children of this object.
-
1
def children_count
-
return (self[right_col_name] - self[left_col_name] - 1)/2
-
end
-
-
# Returns a set of itself and all of its nested children
-
1
def full_set
-
self.class.base_class.find(:all, :conditions => "#{scope_condition} AND (#{left_col_name} BETWEEN #{self[left_col_name]} and #{self[right_col_name]})" )
-
end
-
-
# Returns a set of all of its children and nested children
-
1
def all_children
-
self.class.base_class.find(:all, :conditions => "#{scope_condition} AND (#{left_col_name} > #{self[left_col_name]}) and (#{right_col_name} < #{self[right_col_name]})" )
-
end
-
-
# Returns a set of only this entry's immediate children
-
1
def direct_children
-
self.class.base_class.find(:all, :conditions => "#{scope_condition} and #{parent_column} = #{self.id}", :order => left_col_name)
-
end
-
-
# Prunes a branch off of the tree, shifting all of the elements on the right
-
# back to the left so the counts still work.
-
1
def before_destroy
-
return if self[right_col_name].nil? || self[left_col_name].nil?
-
dif = self[right_col_name] - self[left_col_name] + 1
-
-
self.class.base_class.transaction {
-
self.class.base_class.delete_all( "#{scope_condition} and #{left_col_name} > #{self[left_col_name]} and #{right_col_name} < #{self[right_col_name]}" )
-
self.class.base_class.update_all( "#{left_col_name} = (#{left_col_name} - #{dif})", "#{scope_condition} AND #{left_col_name} >= #{self[right_col_name]}" )
-
self.class.base_class.update_all( "#{right_col_name} = (#{right_col_name} - #{dif} )", "#{scope_condition} AND #{right_col_name} >= #{self[right_col_name]}" )
-
}
-
end
-
end
-
end
-
end
-
end
-
1
module AutoComplete
-
-
1
def self.included(base)
-
1
base.extend(ClassMethods)
-
end
-
-
#
-
# Example:
-
#
-
# # Controller
-
# class BlogController < ApplicationController
-
# auto_complete_for :post, :title
-
# end
-
#
-
# # View
-
# <%= text_field_with_auto_complete :post, title %>
-
#
-
# By default, auto_complete_for limits the results to 10 entries,
-
# and sorts by the given field.
-
#
-
# auto_complete_for takes a third parameter, an options hash to
-
# the find method used to search for the records:
-
#
-
# auto_complete_for :post, :title, :limit => 15, :order => 'created_at DESC'
-
#
-
# For help on defining text input fields with autocompletion,
-
# see ActionView::Helpers::JavaScriptHelper.
-
#
-
# For more examples, see script.aculo.us:
-
# * http://script.aculo.us/demos/ajax/autocompleter
-
# * http://script.aculo.us/demos/ajax/autocompleter_customized
-
1
module ClassMethods
-
1
def auto_complete_for(object, method, options = {})
-
7
define_method("auto_complete_for_#{object}_#{method}") do
-
find_options = {
-
:conditions => [ "LOWER(#{method}) LIKE ?", '%' + params[object][method].downcase + '%' ],
-
:order => "#{method} ASC",
-
:limit => 10 }.merge!(options)
-
-
@items = object.to_s.camelize.constantize.find(:all, find_options)
-
-
render :inline => "<%= auto_complete_result @items, '#{method}' %>"
-
end
-
end
-
end
-
-
end
-
1
module AutoCompleteMacrosHelper
-
# Adds AJAX autocomplete functionality to the text input field with the
-
# DOM ID specified by +field_id+.
-
#
-
# This function expects that the called action returns an HTML <ul> list,
-
# or nothing if no entries should be displayed for autocompletion.
-
#
-
# You'll probably want to turn the browser's built-in autocompletion off,
-
# so be sure to include an <tt>autocomplete="off"</tt> attribute with your text
-
# input field.
-
#
-
# The autocompleter object is assigned to a Javascript variable named <tt>field_id</tt>_auto_completer.
-
# This object is useful if you for example want to trigger the auto-complete suggestions through
-
# other means than user input (for that specific case, call the <tt>activate</tt> method on that object).
-
#
-
# Required +options+ are:
-
# <tt>:url</tt>:: URL to call for autocompletion results
-
# in url_for format.
-
#
-
# Addtional +options+ are:
-
# <tt>:update</tt>:: Specifies the DOM ID of the element whose
-
# innerHTML should be updated with the autocomplete
-
# entries returned by the AJAX request.
-
# Defaults to <tt>field_id</tt> + '_auto_complete'
-
# <tt>:with</tt>:: A JavaScript expression specifying the
-
# parameters for the XMLHttpRequest. This defaults
-
# to 'fieldname=value'.
-
# <tt>:frequency</tt>:: Determines the time to wait after the last keystroke
-
# for the AJAX request to be initiated.
-
# <tt>:indicator</tt>:: Specifies the DOM ID of an element which will be
-
# displayed while autocomplete is running.
-
# <tt>:tokens</tt>:: A string or an array of strings containing
-
# separator tokens for tokenized incremental
-
# autocompletion. Example: <tt>:tokens => ','</tt> would
-
# allow multiple autocompletion entries, separated
-
# by commas.
-
# <tt>:min_chars</tt>:: The minimum number of characters that should be
-
# in the input field before an Ajax call is made
-
# to the server.
-
# <tt>:on_hide</tt>:: A Javascript expression that is called when the
-
# autocompletion div is hidden. The expression
-
# should take two variables: element and update.
-
# Element is a DOM element for the field, update
-
# is a DOM element for the div from which the
-
# innerHTML is replaced.
-
# <tt>:on_show</tt>:: Like on_hide, only now the expression is called
-
# then the div is shown.
-
# <tt>:after_update_element</tt>:: A Javascript expression that is called when the
-
# user has selected one of the proposed values.
-
# The expression should take two variables: element and value.
-
# Element is a DOM element for the field, value
-
# is the value selected by the user.
-
# <tt>:select</tt>:: Pick the class of the element from which the value for
-
# insertion should be extracted. If this is not specified,
-
# the entire element is used.
-
# <tt>:method</tt>:: Specifies the HTTP verb to use when the autocompletion
-
# request is made. Defaults to POST.
-
1
def auto_complete_field(field_id, options = {})
-
function = "var #{field_id}_auto_completer = new Ajax.Autocompleter("
-
function << "'#{field_id}', "
-
function << "'" + (options[:update] || "#{field_id}_auto_complete") + "', "
-
function << "'#{url_for(options[:url])}'"
-
-
js_options = {}
-
js_options[:tokens] = array_or_string_for_javascript(options[:tokens]) if options[:tokens]
-
js_options[:callback] = "function(element, value) { return #{options[:with]} }" if options[:with]
-
js_options[:indicator] = "'#{options[:indicator]}'" if options[:indicator]
-
js_options[:select] = "'#{options[:select]}'" if options[:select]
-
js_options[:paramName] = "'#{options[:param_name]}'" if options[:param_name]
-
js_options[:frequency] = "#{options[:frequency]}" if options[:frequency]
-
js_options[:method] = "'#{options[:method].to_s}'" if options[:method]
-
-
{ :after_update_element => :afterUpdateElement,
-
:on_show => :onShow, :on_hide => :onHide, :min_chars => :minChars }.each do |k,v|
-
js_options[v] = options[k] if options[k]
-
end
-
-
function << (', ' + options_for_javascript(js_options) + ')')
-
-
javascript_tag(function)
-
end
-
-
# Use this method in your view to generate a return for the AJAX autocomplete requests.
-
#
-
# Example action:
-
#
-
# def auto_complete_for_item_title
-
# @items = Item.find(:all,
-
# :conditions => [ 'LOWER(description) LIKE ?',
-
# '%' + request.raw_post.downcase + '%' ])
-
# render :inline => "<%= auto_complete_result(@items, 'description') %>"
-
# end
-
#
-
# The auto_complete_result can of course also be called from a view belonging to the
-
# auto_complete action if you need to decorate it further.
-
1
def auto_complete_result(entries, field, phrase = nil)
-
return unless entries
-
items = entries.map { |entry| content_tag("li", phrase ? highlight(entry[field], phrase) : h(entry[field])) }
-
content_tag("ul", items.uniq)
-
end
-
-
# Wrapper for text_field with added AJAX autocompletion functionality.
-
#
-
# In your controller, you'll need to define an action called
-
# auto_complete_for to respond the AJAX calls,
-
#
-
1
def text_field_with_auto_complete(object, method, tag_options = {}, completion_options = {})
-
(completion_options[:skip_style] ? "" : auto_complete_stylesheet) +
-
text_field(object, method, tag_options) +
-
content_tag("div", "", :id => "#{object}_#{method}_auto_complete", :class => "auto_complete") +
-
auto_complete_field("#{object}_#{method}", { :url => { :action => "auto_complete_for_#{object}_#{method}" } }.update(completion_options))
-
end
-
-
1
private
-
1
def auto_complete_stylesheet
-
content_tag('style', <<-EOT, :type => Mime::CSS)
-
div.auto_complete {
-
width: 350px;
-
background: #fff;
-
}
-
div.auto_complete ul {
-
border:1px solid #888;
-
margin:0;
-
padding:0;
-
width:100%;
-
list-style-type:none;
-
}
-
div.auto_complete ul li {
-
margin:0;
-
padding:3px;
-
}
-
div.auto_complete ul li.selected {
-
background-color: #ffb;
-
}
-
div.auto_complete ul strong.highlight {
-
color: #800;
-
margin:0;
-
padding:0;
-
}
-
EOT
-
end
-
-
end
-
1
require 'action_view/helpers'
-
1
require 'active_support/i18n'
-
1
require 'active_support/core_ext/enumerable'
-
1
require 'active_support/core_ext/object/blank'
-
-
1
module ActionView
-
1
module Helpers
-
# The Active Record Helper makes it easier to create forms for records kept in instance variables. The most far-reaching is the +form+
-
# method that creates a complete form for all the basic content types of the record (not associations or aggregations, though). This
-
# is a great way of making the record quickly available for editing, but likely to prove lackluster for a complicated real-world form.
-
# In that case, it's better to use the +input+ method and the specialized +form+ methods in link:classes/ActionView/Helpers/FormHelper.html
-
1
module DynamicForm
-
# Returns a default input tag for the type of object returned by the method. For example, if <tt>@post</tt>
-
# has an attribute +title+ mapped to a +VARCHAR+ column that holds "Hello World":
-
#
-
# input("post", "title")
-
# # => <input id="post_title" name="post[title]" size="30" type="text" value="Hello World" />
-
1
def input(record_name, method, options = {})
-
InstanceTag.new(record_name, method, self).to_tag(options)
-
end
-
-
# Returns an entire form with all needed input tags for a specified Active Record object. For example, if <tt>@post</tt>
-
# has attributes named +title+ of type +VARCHAR+ and +body+ of type +TEXT+ then
-
#
-
# form("post")
-
#
-
# would yield a form like the following (modulus formatting):
-
#
-
# <form action='/posts/create' method='post'>
-
# <p>
-
# <label for="post_title">Title</label><br />
-
# <input id="post_title" name="post[title]" size="30" type="text" value="Hello World" />
-
# </p>
-
# <p>
-
# <label for="post_body">Body</label><br />
-
# <textarea cols="40" id="post_body" name="post[body]" rows="20"></textarea>
-
# </p>
-
# <input name="commit" type="submit" value="Create" />
-
# </form>
-
#
-
# It's possible to specialize the form builder by using a different action name and by supplying another
-
# block renderer. For example, if <tt>@entry</tt> has an attribute +message+ of type +VARCHAR+ then
-
#
-
# form("entry",
-
# :action => "sign",
-
# :input_block => Proc.new { |record, column|
-
# "#{column.human_name}: #{input(record, column.name)}<br />"
-
# })
-
#
-
# would yield a form like the following (modulus formatting):
-
#
-
# <form action="/entries/sign" method="post">
-
# Message:
-
# <input id="entry_message" name="entry[message]" size="30" type="text" /><br />
-
# <input name="commit" type="submit" value="Sign" />
-
# </form>
-
#
-
# It's also possible to add additional content to the form by giving it a block, such as:
-
#
-
# form("entry", :action => "sign") do |form|
-
# form << content_tag("b", "Department")
-
# form << collection_select("department", "id", @departments, "id", "name")
-
# end
-
#
-
# The following options are available:
-
#
-
# * <tt>:action</tt> - The action used when submitting the form (default: +create+ if a new record, otherwise +update+).
-
# * <tt>:input_block</tt> - Specialize the output using a different block, see above.
-
# * <tt>:method</tt> - The method used when submitting the form (default: +post+).
-
# * <tt>:multipart</tt> - Whether to change the enctype of the form to "multipart/form-data", used when uploading a file (default: +false+).
-
# * <tt>:submit_value</tt> - The text of the submit button (default: "Create" if a new record, otherwise "Update").
-
1
def form(record_name, options = {})
-
record = instance_variable_get("@#{record_name}")
-
record = convert_to_model(record)
-
-
options = options.symbolize_keys
-
options[:action] ||= record.persisted? ? "update" : "create"
-
action = url_for(:action => options[:action], :id => record)
-
-
submit_value = options[:submit_value] || options[:action].gsub(/[^\w]/, '').capitalize
-
-
contents = form_tag({:action => action}, :method =>(options[:method] || 'post'), :enctype => options[:multipart] ? 'multipart/form-data': nil)
-
contents.safe_concat hidden_field(record_name, :id) if record.persisted?
-
contents.safe_concat all_input_tags(record, record_name, options)
-
yield contents if block_given?
-
contents.safe_concat submit_tag(submit_value)
-
contents.safe_concat('</form>')
-
end
-
-
# Returns a string containing the error message attached to the +method+ on the +object+ if one exists.
-
# This error message is wrapped in a <tt>DIV</tt> tag by default or with <tt>:html_tag</tt> if specified,
-
# which can be extended to include a <tt>:prepend_text</tt> and/or <tt>:append_text</tt> (to properly explain
-
# the error), and a <tt>:css_class</tt> to style it accordingly. +object+ should either be the name of an
-
# instance variable or the actual object. The method can be passed in either as a string or a symbol.
-
# As an example, let's say you have a model <tt>@post</tt> that has an error message on the +title+ attribute:
-
#
-
# <%= error_message_on "post", "title" %>
-
# # => <div class="formError">can't be empty</div>
-
#
-
# <%= error_message_on @post, :title %>
-
# # => <div class="formError">can't be empty</div>
-
#
-
# <%= error_message_on "post", "title",
-
# :prepend_text => "Title simply ",
-
# :append_text => " (or it won't work).",
-
# :html_tag => "span",
-
# :css_class => "inputError" %>
-
# # => <span class="inputError">Title simply can't be empty (or it won't work).</span>
-
1
def error_message_on(object, method, *args)
-
options = args.extract_options!
-
unless args.empty?
-
ActiveSupport::Deprecation.warn('error_message_on takes an option hash instead of separate ' +
-
'prepend_text, append_text, html_tag, and css_class arguments', caller)
-
-
options[:prepend_text] = args[0] || ''
-
options[:append_text] = args[1] || ''
-
options[:html_tag] = args[2] || 'div'
-
options[:css_class] = args[3] || 'formError'
-
end
-
options.reverse_merge!(:prepend_text => '', :append_text => '', :html_tag => 'div', :css_class => 'formError')
-
-
object = convert_to_model(object)
-
-
if (obj = (object.respond_to?(:errors) ? object : instance_variable_get("@#{object}"))) &&
-
(errors = obj.errors[method]).presence
-
content_tag(options[:html_tag],
-
(options[:prepend_text].html_safe << errors.first).safe_concat(options[:append_text]),
-
:class => options[:css_class]
-
)
-
else
-
''
-
end
-
end
-
-
# Returns a string with a <tt>DIV</tt> containing all of the error messages for the objects located as instance variables by the names
-
# given. If more than one object is specified, the errors for the objects are displayed in the order that the object names are
-
# provided.
-
#
-
# This <tt>DIV</tt> can be tailored by the following options:
-
#
-
# * <tt>:header_tag</tt> - Used for the header of the error div (default: "h2").
-
# * <tt>:id</tt> - The id of the error div (default: "errorExplanation").
-
# * <tt>:class</tt> - The class of the error div (default: "errorExplanation").
-
# * <tt>:object</tt> - The object (or array of objects) for which to display errors,
-
# if you need to escape the instance variable convention.
-
# * <tt>:object_name</tt> - The object name to use in the header, or any text that you prefer.
-
# If <tt>:object_name</tt> is not set, the name of the first object will be used.
-
# * <tt>:header_message</tt> - The message in the header of the error div. Pass +nil+
-
# or an empty string to avoid the header message altogether. (Default: "X errors
-
# prohibited this object from being saved").
-
# * <tt>:message</tt> - The explanation message after the header message and before
-
# the error list. Pass +nil+ or an empty string to avoid the explanation message
-
# altogether. (Default: "There were problems with the following fields:").
-
#
-
# To specify the display for one object, you simply provide its name as a parameter.
-
# For example, for the <tt>@user</tt> model:
-
#
-
# error_messages_for 'user'
-
#
-
# You can also supply an object:
-
#
-
# error_messages_for @user
-
#
-
# This will use the last part of the model name in the presentation. For instance, if
-
# this is a MyKlass::User object, this will use "user" as the name in the String. This
-
# is taken from MyKlass::User.model_name.human, which can be overridden.
-
#
-
# To specify more than one object, you simply list them; optionally, you can add an extra <tt>:object_name</tt> parameter, which
-
# will be the name used in the header message:
-
#
-
# error_messages_for 'user_common', 'user', :object_name => 'user'
-
#
-
# You can also use a number of objects, which will have the same naming semantics
-
# as a single object.
-
#
-
# error_messages_for @user, @post
-
#
-
# If the objects cannot be located as instance variables, you can add an extra <tt>:object</tt> parameter which gives the actual
-
# object (or array of objects to use):
-
#
-
# error_messages_for 'user', :object => @question.user
-
#
-
# NOTE: This is a pre-packaged presentation of the errors with embedded strings and a certain HTML structure. If what
-
# you need is significantly different from the default presentation, it makes plenty of sense to access the <tt>object.errors</tt>
-
# instance yourself and set it up. View the source of this method to see how easy it is.
-
1
def error_messages_for(*params)
-
5
options = params.extract_options!.symbolize_keys
-
-
5
objects = Array.wrap(options.delete(:object) || params).map do |object|
-
5
object = instance_variable_get("@#{object}") unless object.respond_to?(:to_model)
-
5
object = convert_to_model(object)
-
-
5
if object.class.respond_to?(:model_name)
-
5
options[:object_name] ||= object.class.model_name.human.downcase
-
end
-
-
5
object
-
end
-
-
5
objects.compact!
-
10
count = objects.inject(0) {|sum, object| sum + object.errors.count }
-
-
5
unless count.zero?
-
1
html = {}
-
1
[:id, :class].each do |key|
-
2
if options.include?(key)
-
value = options[key]
-
html[key] = value unless value.blank?
-
else
-
2
html[key] = 'errorExplanation'
-
end
-
end
-
1
options[:object_name] ||= params.first
-
-
1
I18n.with_options :locale => options[:locale], :scope => [:errors, :template] do |locale|
-
1
header_message = if options.include?(:header_message)
-
options[:header_message]
-
else
-
1
locale.t :header, :count => count, :model => options[:object_name].to_s.gsub('_', ' ')
-
end
-
-
1
message = options.include?(:message) ? options[:message] : locale.t(:body)
-
-
1
error_messages = objects.sum do |object|
-
1
object.errors.full_messages.map do |msg|
-
3
content_tag(:li, msg)
-
end
-
end.join.html_safe
-
-
1
contents = ''
-
1
contents << content_tag(options[:header_tag] || :h2, header_message) unless header_message.blank?
-
1
contents << content_tag(:p, message) unless message.blank?
-
1
contents << content_tag(:ul, error_messages)
-
-
1
content_tag(:div, contents.html_safe, html)
-
end
-
else
-
4
''
-
end
-
end
-
-
1
private
-
-
1
def all_input_tags(record, record_name, options)
-
input_block = options[:input_block] || default_input_block
-
record.class.content_columns.collect{ |column| input_block.call(record_name, column) }.join("\n")
-
end
-
-
1
def default_input_block
-
Proc.new { |record, column| %(<p><label for="#{record}_#{column.name}">#{column.human_name}</label><br />#{input(record, column.name)}</p>) }
-
end
-
-
1
module InstanceTagMethods
-
1
def to_tag(options = {})
-
case column_type
-
when :string
-
field_type = @method_name.include?("password") ? "password" : "text"
-
to_input_field_tag(field_type, options)
-
when :text
-
to_text_area_tag(options)
-
when :integer, :float, :decimal
-
to_input_field_tag("text", options)
-
when :date
-
to_date_select_tag(options)
-
when :datetime, :timestamp
-
to_datetime_select_tag(options)
-
when :time
-
to_time_select_tag(options)
-
when :boolean
-
to_boolean_select_tag(options)
-
end
-
end
-
-
1
def column_type
-
object.send(:column_for_attribute, @method_name).type
-
end
-
end
-
-
1
module FormBuilderMethods
-
1
def error_message_on(method, *args)
-
@template.error_message_on(@object || @object_name, method, *args)
-
end
-
-
1
def error_messages(options = {})
-
@template.error_messages_for(@object_name, objectify_options(options))
-
end
-
end
-
end
-
-
1
class InstanceTag
-
1
include DynamicForm::InstanceTagMethods
-
end
-
-
1
class FormBuilder
-
1
include DynamicForm::FormBuilderMethods
-
end
-
end
-
end
-
-
1
I18n.load_path << File.expand_path("../../locale/en.yml", __FILE__)
-
1
require 'action_view/helpers/dynamic_form'
-
-
1
class ActionView::Base
-
1
include DynamicForm
-
end
-
1
module GC4R
-
-
1
module GoogleChartsModule #:nodoc:
-
1
def self.included(mod)
-
1
mod.extend(ClassMethods)
-
end
-
1
module ClassMethods
-
1
def use_google_charts
-
1
include GC4R::API
-
end
-
end
-
end # GoogleCharts
-
-
-
1
module GoogleChartsObject #:nodoc:
-
1
def create
-
get_param + '=' + get_value
-
end
-
1
def get_param
-
end
-
1
def get_value
-
end
-
1
def valid?
-
end
-
1
def expand_multiple data, delimiter = "|"
-
if data.is_a?(Array)
-
data.join delimiter
-
else
-
data
-
end
-
end
-
1
def validates value
-
!value.nil?
-
end
-
end
-
1
module GoogleChartContainer
-
1
def create
-
uri = []
-
@params.each do |param|
-
if param.valid?
-
uri << param.create
-
end
-
end
-
uri.join "&"
-
end
-
1
def add(param)
-
@params ||= []
-
@params << param
-
end
-
1
def valid? # if at least on child is valid
-
valid = false;
-
@params.each do |param|
-
valid ||= param.valid?
-
end
-
valid
-
end
-
end
-
1
class ChartContainer
-
1
include GoogleChartContainer
-
end
-
-
# objects
-
1
class Chart < Struct.new :chart_type
-
1
include GoogleChartsObject
-
1
def get_param
-
'cht'
-
end
-
1
def get_value
-
chart_type
-
end
-
1
def valid?
-
validates chart_type
-
end
-
end
-
1
class ChartSize < Struct.new :width, :height
-
1
include GoogleChartsObject
-
1
def get_param
-
'chs'
-
end
-
1
def get_value
-
width.to_s + 'x' + height.to_s
-
end
-
1
def valid?
-
!width.nil? and !height.nil?
-
end
-
end
-
-
# data
-
1
class ChartData < Struct.new :datasets, :min, :max
-
1
include GoogleChartsObject
-
1
def get_param
-
'chd'
-
end
-
1
def get_value
-
if datasets[0].is_a?(Array)
-
't:' + datasets.map{ |value| mangle(value).join(",") }.join("|")
-
else
-
't:' + mangle(datasets).join(",")
-
end
-
end
-
1
def valid?
-
!datasets.nil? && !datasets.empty?
-
end
-
1
private
-
1
def mangle dataset
-
dataset.map do |value|
-
if value.nil?
-
-1
-
else
-
value
-
end
-
end
-
end
-
end
-
1
class ChartDataScale < Struct.new :min, :max
-
1
include GoogleChartsObject
-
1
def get_param
-
"chds"
-
end
-
1
def get_value
-
min.to_s + ',' + max.to_s
-
end
-
1
def valid?
-
!min.nil? && !max.nil?
-
end
-
end
-
1
class ChartDataColor < Struct.new :colors
-
1
include GoogleChartsObject
-
1
def get_param
-
"chco"
-
end
-
1
def get_value
-
expand_multiple colors, ","
-
end
-
1
def valid?
-
!colors.nil? && !colors.empty?
-
end
-
end
-
1
class ChartDataLegend < Struct.new :names
-
1
include GoogleChartsObject
-
1
def get_param
-
'chdl'
-
end
-
1
def get_value
-
expand_multiple names
-
end
-
1
def valid?
-
# TODO hack
-
!names.nil? && !names.empty?
-
end
-
end
-
1
class ChartDataPieLabels < Struct.new :names #TODO hack, hack hack
-
1
include GoogleChartsObject
-
1
def get_param
-
'chl'
-
end
-
1
def get_value
-
expand_multiple names
-
end
-
1
def valid?
-
# TODO hack
-
!names.nil? && !names.empty?
-
end
-
end
-
1
class ChartAxis < Struct.new :axis
-
1
include GoogleChartsObject
-
1
def get_param
-
'chxt'
-
end
-
1
def get_value
-
expand_multiple axis, ","
-
end
-
1
def valid?
-
validates axis
-
end
-
end
-
1
class ChartAxisLabels < Struct.new :labels
-
1
include GoogleChartsObject
-
1
def get_param
-
'chxl'
-
end
-
1
def get_value
-
labels
-
end
-
1
def valid?
-
validates labels
-
end
-
end
-
# title
-
1
class ChartTitleSize < Struct.new :color, :fontsize
-
1
include GoogleChartsObject
-
1
def get_param
-
'chts'
-
end
-
1
def get_value
-
color + ',' + fontsize.to_s
-
end
-
1
def valid?
-
!color.nil? and !fontsize.nil?
-
end
-
end
-
1
class ChartTitleName < Struct.new :title
-
1
include GoogleChartsObject
-
1
def get_param
-
'chtt'
-
end
-
1
def get_value
-
expand_multiple title
-
end
-
1
def valid?
-
validates title
-
end
-
end
-
1
class ChartTitle < ChartContainer
-
1
def initialize options = {}
-
add ChartTitleName.new(options[:title])
-
add ChartTitleSize.new(options[:color], options[:fontsize])
-
end
-
end
-
-
#
-
# GC4R exported API
-
#
-
1
module API #:nodoc:
-
# base chart
-
1
class GoogleChart < GC4R::ChartContainer
-
1
GOOGLE_CHART_URL = 'http://chart.apis.google.com/chart?'
-
1
HELLO_WORLD = "cht=p3&chd=t:60,40&chs=250x100&chl=Hello|World"
-
1
def initialize options={}
-
add Chart.new(options[:chart_type])
-
add ChartTitle.new(options)
-
add ChartSize.new(options[:width], options[:height])
-
end
-
1
def to_url
-
uri = create
-
if uri.nil? || uri.empty?
-
uri = HELLO_WORLD
-
end
-
url = GOOGLE_CHART_URL + uri
-
puts "Google Chart: #{url}"
-
url
-
end
-
1
def data=(d)
-
add d
-
end
-
1
def axis=(a)
-
add a
-
end
-
end
-
-
# chart types
-
1
class GoogleLineChart < GoogleChart
-
1
SIMPLE = 'lc'
-
1
XY = 'lxy'
-
1
def initialize options={}
-
options[:chart_type] ||= SIMPLE
-
super
-
end
-
end
-
1
class GoogleSparklinesChart < GoogleChart
-
1
def initialize options = {}
-
options[:chart_type] = "ls"
-
super
-
end
-
end
-
1
class GoogleBarChart < GoogleChart
-
1
VERTICAL = 'bvs'
-
1
HORIZONTAL = 'bhs'
-
1
def initialize options = {}
-
options[:chart_type] ||= VERTICAL
-
super
-
end
-
end
-
1
class GooglePieChart < GoogleChart
-
1
PIE_2D = 'p'
-
1
PIE_3D = 'p3'
-
1
def initialize options = {}
-
options[:chart_type] ||= PIE_2D
-
super
-
end
-
end
-
1
class GoogleScatterPlotsChart < GoogleChart
-
1
def initialize options = {}
-
options[:chart_type] = "s"
-
super
-
end
-
end
-
-
# data and dataset
-
1
class GoogleChartDataset
-
1
attr_accessor :data, :color, :title
-
1
def initialize options={}
-
@data = options[:data]
-
@color = options[:color]
-
@title = options[:title]
-
end
-
end
-
1
class GoogleChartData < ChartContainer
-
1
def initialize options = {}
-
datasets = []
-
colors = []
-
legend = []
-
if options[:datasets].is_a?(Array)
-
options[:datasets].each do |dataset|
-
datasets << dataset.data
-
colors << dataset.color
-
legend << dataset.title
-
end
-
else
-
datasets << options[:datasets].data
-
colors << options[:datasets].color
-
legend << options[:datasets].title
-
end
-
add ChartData.new(datasets.compact)
-
add ChartDataColor.new(colors.compact)
-
add ChartDataLegend.new(legend.compact)
-
add ChartDataPieLabels.new(legend.compact)
-
add ChartDataScale.new(options[:min], options[:max])
-
end
-
end
-
# axis
-
1
class GoogleChartAxis < ChartContainer
-
1
LEFT = 'y'
-
1
BOTTOM = 'x'
-
1
RIGHT = 'r'
-
1
TOP = 't'
-
1
def initialize options={}
-
add ChartAxis.new options[:axis]
-
end
-
end
-
end
-
-
-
end
-
-
1
class DotGraphPrinter
-
1
attr_accessor :orientation, :size, :color
-
-
# The following can be set to blocks of code that gives a default
-
# value for the node shapes, node labels and link labels, respectively.
-
1
attr_accessor :node_shaper, :node_labeler, :link_labeler
-
-
# A node shaper maps each node to a string describing its shape.
-
# Valid shapes are:
-
# "ellipse" (default)
-
# "box"
-
# "circle"
-
# "plaintext" (no outline)
-
# "doublecircle"
-
# "diamond"
-
# Not yet supported or untested once are:
-
# "polygon", "record", "epsf"
-
1
@@default_node_shaper = proc{|n| "box"}
-
-
1
@@default_node_labeler = proc{|n|
-
if Symbol===n
-
n.id2name
-
elsif String===n
-
n
-
else
-
n.inspect
-
end
-
}
-
-
1
@@default_link_labeler = proc{|info| info ? info.inspect : nil}
-
-
# links is either array of
-
# arrays [fromNode, toNode [, infoOnLink]], or
-
# objects with attributes :from, :to, :info
-
# nodes is array of node objects
-
# All nodes used in the links are used as nodes even if they are not
-
# in the "nodes" parameters.
-
1
def initialize(links = [], nodes = [])
-
@links, @nodes = links, add_nodes_in_links(links, nodes)
-
@node_attributes, @edge_attributes = Hash.new, Hash.new
-
set_default_values
-
end
-
-
1
def set_default_values
-
@color = "black"
-
@size = "9,11"
-
@orientation = "portrait"
-
@node_shaper = @@default_node_shaper
-
@node_labeler = @@default_node_labeler
-
@link_labeler = @@default_link_labeler
-
end
-
-
1
def write_to_file(filename, fileType = "ps")
-
dotfile = temp_filename(filename)
-
File.open(dotfile, "w") {|f| f.write to_dot_specification}
-
system "dot -T#{fileType} -o #{filename} #{dotfile}"
-
File.delete(dotfile)
-
end
-
-
1
def set_edge_attributes(anEdge, aHash)
-
# TODO check if attributes are valid dot edge attributes
-
edge = find_edge(anEdge)
-
set_attributes(edge, @edge_attributes, true, aHash)
-
end
-
-
1
def set_node_attributes(aNode, aHash)
-
# TODO check if attributes are valid dot node attributes
-
set_attributes(aNode, @node_attributes, true, aHash)
-
end
-
-
1
def to_dot_specification
-
set_edge_labels(@links)
-
set_node_labels_and_shape(@nodes)
-
"digraph G {\n" +
-
graph_parameters_to_dot_specification +
-
@nodes.uniq.map {|n| format_node(n)}.join(";\n") + ";\n" +
-
@links.uniq.map {|l| format_link(l)}.join(";\n") + ";\n" +
-
"}"
-
end
-
-
1
protected
-
-
1
def find_edge(anEdge)
-
@links.each do |link|
-
return link if source_and_dest(link) == source_and_dest(anEdge)
-
end
-
end
-
-
1
def set_attributes(key, hash, override, newAttributeHash)
-
h = hash[key] || Hash.new
-
newAttributeHash = all_keys_to_s(newAttributeHash)
-
newAttributeHash.each do |k, value|
-
h[k] = value unless h[k] and !override
-
end
-
hash[key] = h
-
end
-
-
1
def graph_parameters_to_dot_specification
-
"graph [\n" +
-
(self.size ? " size = #{@size.inspect},\n" : "") +
-
(self.orientation ? " orientation = #{@orientation},\n" : "") +
-
(self.color ? " color = #{@color}\n" : "") +
-
"]\n"
-
end
-
-
1
def each_node_in_links(links)
-
links.each do |l|
-
src, dest = source_and_dest(l)
-
yield src
-
yield dest
-
end
-
end
-
-
1
def add_nodes_in_links(links, nodes)
-
new_nodes = []
-
each_node_in_links(links) {|node| new_nodes.push node}
-
(nodes + new_nodes).uniq
-
end
-
-
1
def all_keys_to_s(aHash)
-
# MAYBE reuse existing hash?
-
Hash[*(aHash.map{|p| p[0] = p[0].to_s; p}.flatten)]
-
end
-
-
1
def set_edge_labels(edges)
-
edges.each do |edge|
-
src, dest, info = get_link_data(edge)
-
if info
-
label = @link_labeler.call(info)
-
set_attributes(edge, @edge_attributes, false, :label =>label) if label
-
end
-
end
-
end
-
-
1
def set_node_labels_and_shape(nodes)
-
nodes.each do |node|
-
set_attributes(node, @node_attributes, false,
-
:label => @node_labeler.call(node).inspect,
-
:shape => @node_shaper.call(node).inspect)
-
end
-
end
-
-
1
def get_link_data(link)
-
begin
-
return link.from, link.to, link.info
-
rescue Exception
-
return link[0], link[1], link[2]
-
end
-
end
-
-
1
def source_and_dest(link)
-
get_link_data(link)[0,2]
-
end
-
-
1
def format_attributes(attributes)
-
return "" unless attributes
-
strings = attributes.map {|a, v| "#{a}=#{v}"}
-
strings.length > 0 ? (" [" + strings.join(", ") + "]") : ("")
-
end
-
-
1
def mangle_node_name(node)
-
"n" + node.hash.abs.inspect
-
end
-
-
1
def format_link(link)
-
from, to, info = get_link_data(link)
-
mangle_node_name(from) + " -> " + mangle_node_name(to) +
-
format_attributes(@edge_attributes[link])
-
end
-
-
1
def format_node(node)
-
mangle_node_name(node) + format_attributes(@node_attributes[node])
-
end
-
-
1
def temp_filename(base = "tmp")
-
tmpfile = base + rand(100000).inspect
-
while test(?f, tmpfile)
-
tmpfile = base + rand(100000).inspect
-
end
-
tmpfile
-
end
-
end
-
1
module RedboxHelper
-
-
1
def link_to_redbox(name, id, html_options = {})
-
@uses_redbox = true
-
link_to_function name, "RedBox.showInline('#{id.to_s}')", html_options
-
end
-
-
1
def link_to_component_redbox(name, url_options = {}, html_options = {})
-
@uses_redbox = true
-
id = id_from_url(url_options, html_options[:id])
-
link_to_redbox(name, id, html_options) + content_tag("span", render_component(url_options), :id => id, :style => 'display: none;')
-
end
-
-
1
def link_to_remote_redbox(name, link_to_remote_options = {}, html_options = {})
-
@uses_redbox = true
-
id = id_from_url(link_to_remote_options[:url], html_options[:id])
-
hidden_content_id = "hidden_content_#{id}"
-
link_to_remote_options = redbox_remote_options(link_to_remote_options, hidden_content_id)
-
-
return build_hidden_content(hidden_content_id) + link_to_remote(name, link_to_remote_options, html_options)
-
end
-
-
1
def link_to_close_redbox(name, html_options = {})
-
@uses_redbox = true
-
link_to_function name, 'RedBox.close()', html_options
-
end
-
-
1
def button_to_close_redbox(name, html_options = {})
-
@uses_redbox = true
-
button_to_function name, 'RedBox.close()', html_options
-
end
-
-
1
def launch_remote_redbox(link_to_remote_options = {}, html_options = {})
-
@uses_redbox = true
-
id = id_from_url(link_to_remote_options[:url], html_options[:id])
-
hidden_content_id = "hidden_content_#{id}"
-
hidden_content = build_hidden_content(hidden_content_id)
-
link_to_remote_options = redbox_remote_options(link_to_remote_options, hidden_content_id)
-
-
return build_hidden_content(hidden_content_id) + javascript_tag(remote_function(link_to_remote_options))
-
end
-
-
1
private
-
-
1
def id_from_url(url_options, link_id)
-
result = ''
-
result = link_id.to_s + '_' unless link_id.nil?
-
-
if url_options.nil?
-
raise ArgumentError, 'You are trying to create a RedBox link without specifying a valid url.'
-
elsif url_options.is_a? String
-
result + url_options.delete(":/")
-
else
-
result + url_to_id_string(url_options.values.join('_'))
-
end
-
end
-
-
1
def url_to_id_string(value)
-
value.sub(/[?=&]/, '')
-
end
-
-
1
def build_hidden_content(hidden_content_id)
-
content_tag("div", '', :id => hidden_content_id, :style => 'display: none;')
-
end
-
-
1
def redbox_remote_options(remote_options, hidden_content_id)
-
remote_options[:update] = hidden_content_id unless remote_options.key?(:update)
-
remote_options[:loading] = "RedBox.loading();" + remote_options[:loading].to_s
-
if remote_options[:update]
-
remote_options[:complete] = "RedBox.addHiddenContent('#{hidden_content_id}'); " + remote_options[:complete].to_s
-
else
-
remote_options[:complete] = "RedBox.activateRBWindow(); " + remote_options[:complete].to_s
-
end
-
remote_options
-
end
-
-
-
end